Thank for your patience.
I think I were just scared with what Crockford wrote. :)


On Thu, Dec 23, 2010 at 11:42 PM, Dmitry A. Soshnikov
<dmitry.soshni...@gmail.com> wrote:
> On 23.12.2010 17:54, Yu-Hsuan Lai wrote:
>
> I think I have totally understood your code, but is this the using
> "new" which "Good Part" try to avoid?
>
> I think the book you read consider `new` as `evil` because of two reasons:
> (1) to avoid a similarity with a class-based systems such as Java (to setup
> your mind to think in a prototype-based paradigm), and (2) to scare children
> ;).
>
> The first reason could be considered as a noble only if there would be no
> one "but...". As you know, the ability to _generate_ objects isn't yet
> considered as an ability to _classify_. In case of several (many) similar
> objects with the same state, we need a some convenient way to generate
> objects. E.g.:
>
> var point = {x: 1, y: 2};
>
> If we need several points:
>
> var a = {x: 1, y: 2};
> var b = {x: 3, y: 4};
> var c = {x: 5, y: 6};
>
> But obviously, a copy-paste code reuse stylistic isn't a professional way to
> program (what if you need 100, 1000 such objects?). Of course we need an
> elegant way to reuse the generation of points. The easiest way is to use a
> simple function (as you always do in case when the code is repeated more
> than two times -- so-called a "rule of two": "If something apears in the
> code more than two times -- move (encapsulate) it into a function"):
>
> function makePoint(x, y) {
>   return {
>     x: x,
>     y: y
>   };
> }
>
> var a = makePoint(1, 2);
> var b = makePoint(3, 4);
> var c = makePoint(5, 6);
>
> I guess the profit is obvious -- if later the the internal state of a point
> will change, we should edit only one place. So, the main purpose of a
> constructor (once again) is to conveniently reuse the code and to generate
> objects of the same structure.
>
> However, to be able to classify your objects (i.e. to distinguish them from
> other objects with the same structure), you need to use a some
> classification tag (simply a some property, which help to uniquely
> differentiate your objects). You could place it directly on the point object
> itself, but it's not efficient since the same property is created every time
> on every object. Instead, you may create a helper shared object which will
> store common properties of all points. To not place this helper object in
> the global scope, you may store it as a property of your `makePoint`
> function. Thus, a helper object is called a `prototype` and the
> classification tag -- `constructor`:
>
> makePoint.prototype = {
>   constrcutor: makePoint
> };
>
> And modified way of creation:
>
> function makePoint(x, y) {
>   return {
>     __proto__: makePoint.prototype,
>     x: x,
>     y: y
>   };
> }
>
> Then you need to implement the ability to get the classification tag
> directly from the instances. It's simple: if a property isn't found on the
> object, continue the lookup in its __proto__ link.
>
> a.constructor // a.constructor -> not found, a.__proto__.constructor ->
> found == makePoint.
>
> Having implemented this, you may want to sugar somehow your "makePoint"
> factory. You can: (1) remove "make" prefix (replace it with `new` keyword),
> (2) make `return` implicit, (3) set __proto__ also implicitly, (4) do not
> explicitly use {} every time, but use a special keyword to reference the
> newly created object (e.g. `this`). That's how you'll get the constructors
> system implemented in JS:
>
> function Point() { // no "make"
>   this.x = x;
>   this.y = y;
> }
>
> var a = new Point(1, 2);
> var b = new Point(3, 4);
> var c = new Point(5, 6);
>
> a.constructor // Point
>
> So from this viewpoint, you see that `new` keyword (if you really understand
> "what's is going on here" but not just want to scare children which didn't
> heard that word "prototype") isn't evil at all. It's just a sugar for your
> factory function. There is no a big difference between "make me a point" and
> "construct me a new point".
>
> Of course, if you don't need a classification, you may simply inherit from
> other objects just setting their __proto__ reference (what exactly is made
> inside the `Object.create`).
>
> By the way, ECMAScript itself classifies its objects. And not surprisingly
> with the classification tag which is called the same -- [[Class]]. E.g.:
>
> var a = {};
> var b = [];
>
> // both are objects
> alert([typeof a, typeof b]); // "object", "object"
>
> // but have different classification tags
> var getClass = Object.prototype.toString;
>
> alert([getClass.call(a), getClass.call(b)]); // "[object Object]", "[object
> Array]"
>
> "An even better coping strategy is to not use new at all."
> In fact, I don't regard your classical implementation bad. This is the
> reason why I'm so confused.
>
>
> Only you decide what is better for your system -- where you need classified
> objects or you just want to inherit them in the unclassified manner.
>
> Is this an "even better strategy"?
> var a={x:10};
> b=Object.create(a);
> b.x = 20;
> b.y = 30;
>
>
> Yes, quite a good solution also. Why not?
>
> I can't realize its advantages. Crockford gave me am impression: "new
> is evil, prototype is beautiful."
>
> Always remember that strong phrases are not analytic.
>
> (he put "new" in the "bad parts")
> Did he exaggerate or I misunderstand him?
>
>
> Analyze. Once you see the reasons for what this or that construction is here
> (in the language), you will have your meaning on the question and may decide
> yourself what is bad and what's not.
>
> (I know in previous post you have tried to answer me... but maybe I'm
> not enough clever to understand it)
>
>
> The topic in truth is easier than it looks and easier than some trying to
> explain it in books. As you saw, there is no big differences between
> classical and protoypal approaches. Again, the main difference is in the
> classified and unclassified concepts. And all the other stuff (sugar for
> creation, etc) is derived.
>
> Dmitry.
>
> On Thu, Dec 23, 2010 at 8:13 PM, Dmitry A. Soshnikov
> <dmitry.soshni...@gmail.com> wrote:
>
> On 23.12.2010 14:54, Yu-Hsuan Lai wrote:
>
> Where is " context of your child object"?
>
>
> It's a this value.
>
> 1. Parent constructor:
>
> function A(x) {
>   this.x = x;
> }
>
> A.prototype.foo = function () {
>   return this.x;
> };
>
> // and instance of the constructor "A"
> var a = new A(10);
>
> // has an own "x" property
> alert(a.x);
>
> // and a classification tag "constructor", which
> // is an inherited property placed on the prototype
> alert(a.constructor === A); // true
>
> 2. Child constructor
>
> function B(x, y) {
>
>   // apply the parent constructor
>   // in context of the child object
>   A.apply(this, arguments);
>
>   // create an own property
>   this.y = y;
> }
>
> // inherit from A.prototype
> B.prototype.__proto__ = A.prototype;
>
> var b = new B(20, 30);
>
> // "b" object has own "x" and "y" properties
> alert([b.x, b.y]); // 10, 20
>
> // and "classified" as "B"
> alert(b.constructor === B); // true
>
> Notice how "b" got its "x" property via A.apply(this, arguments)? This is
> called to apply a function in context of the needed object (`this` value
> references to a newly created object, that is, to "b" at working of B
> constructor) .
>
> P.S.: notice also, I used non-standard inheritance way with __proto__ to
> simplify explanation.
>
> Dmitry.
>
> On Thu, Dec 23, 2010 at 6:37 PM, Dmitry A. Soshnikov
> <dmitry.soshni...@gmail.com> wrote:
>
> On 23.12.2010 11:37, Yu-Hsuan Lai wrote:
>
> In fact, even though I just want some public variants, I still have the same
> problem.
> var obj = {a:1,b:2,c:3 ... some methods...};
> obj2 = Object.create(obj);
> obj2.a is referred to obj.a, right? If I want another instance, I have to
> write obj2.a = 1;
>
> Yes, this exactly one of the differences. In a class-based system all
> properties are copied to the class descendant (even if some of them are not
> needed at deeper classes). In a prototype-based system the state
> (properties) as well as behavior (methods) are inherited.
>
> But if the object is very "big"? Write a function to assign all variants? Is
> it "constructor"?
>
> A constructor is used to generate (usually more than one) objects of a
> needed "classification" (a "classification" tag which may help to
> distinguish one object from another is stored usually in the inherited
> `constructor` property of an object, e.g. a.constructor == A ? where `A` is
> a constructor of `a` instance). It's a factory which generates the objects.
> If you need only one unclassified object, there is no big need in the
> constructor. You may use e.g. an object initialiser to create an object: a =
> {}. To inherit from another, you (as you know) may use Object.create(proto,
> [props]).
>
> To create an own state in this case, yes, you should manually copy needed
> properties to the child object. In case of using constructor, you may apply
> needed function in context of your child object. Though, it isn't differ
> much from the same manual creation of needed own properties -- in any case
> you describe them in the parent constructor.
>
>
> Once I implement these all, my prototypal OO still is different from
> classical OO?
>
> No so much. You may generate (with constructors) and "classify" (with
> classification tag -- the property "constructor") your objects. You don't
> inherit the state but have the own one for child objects. You inherit
> methods with linear systematized chain. It's a class-based system. I.e. with
> a prototype-based system it's easy to implement the class-based system. But
> not a vice-versa.
>
> Dmitry.
>
> On Thu, Dec 23, 2010 at 3:14 PM, אריה גלזר <arieh.gla...@gmail.com> wrote:
>
> This is exacatly the point - you create the methods and the variable
> together, so either you get a copy of all of them, or you get a new
> instance.
> But if you want a 'private' variable for each instance, the only way you are
> going to achieve this (I think) is by creating a separate closure for each
> object creation. So you can either do the above second solution, or you can
> do
> var obj = {
>         getA : function getA() {
>             return this.a;
>         },
>         setA : function setA(b) {
>             a = this.b;
>         }
>     };
>
> function F(){ this.a = 'a';}
> for (i =0; i<10;i++) x.push((function(){ F.prototype = obj; return new
> F();})();
>
> And you will still be exposing a in the end. But the point is, this is much
> less readable and performance-wise I don't think it really matters, so your
> second pattern is good enough IMO.
>
> note - this list beeing so heavy on js wizards, I'm always a little afraid
> of posting comments here...
>
>
> On Thu, Dec 23, 2010 at 8:23 AM, Yu-Hsuan Lai <rainco...@gmail.com> wrote:
>
> I'm trying use prototypal inheritance instead of classical one. But I'm
> still confused.
> I can't complete very very very small tasks, like this one:
> Create 10 copies of a object(with a private variant and public functions to
> access it) in an array.
> I have two way to approach it, first is to use Object#create:
> var x=[];
> x[0]=(function () {
>     var a=10;
>     return {
>         getA : function getA() {
>             return a;
>         },
>         setA : function setA(b) {
>             a = b;
>         }
>     };
> })();
> for(var i=1; i<10; i++)
>     x[i] = Object.create(x[0]);
> But all 10 objects' "a"s refer to a single integer. Tragedy.
> My second way is call a function which return a object 10 times:
> function createX() {
>     var a=10;
>     return {
>         getA : function getA() {
>             return a;
>         },
>         setA : function setA(b) {
>             a = b;
>         }
>     };
> }
> var x=[];
> for(var i=0; i<10; i++)
>     x[i] = createX();
> It works. But every x has its own "getA" and "setA" instance. In contrast to
> the former, it costs more memory.
> I know it maybe doesn't matter. But knowing prototypal OO can use only one
> instance, creating 10 let me regard me as a stupid.
> Except the two methods, the only one method I can figure out is... classical
> OO.
> Is it avoidable?
>
>
> --
> Lai, Yu-Hsuan
> --
> To view archived discussions from the original JSMentors Mailman list:
> http://www.mail-archive.com/jsmentors@jsmentors.com/
>
> To search via a non-Google archive, visit here:
> http://www.mail-archive.com/jsmentors@googlegroups.com/
>
> To unsubscribe from this group, send email to
> jsmentors+unsubscr...@googlegroups.com
>
>
> --
> Arieh Glazer
> אריה גלזר
> 052-5348-561
> http://www.arieh.co.il
> http://www.link-wd.co.il
> --
> To view archived discussions from the original JSMentors Mailman list:
> http://www.mail-archive.com/jsmentors@jsmentors.com/
>
> To search via a non-Google archive, visit here:
> http://www.mail-archive.com/jsmentors@googlegroups.com/
>
> To unsubscribe from this group, send email to
> jsmentors+unsubscr...@googlegroups.com
>
>
> --
> Lai, Yu-Hsuan
> --
> To view archived discussions from the original JSMentors Mailman list:
> http://www.mail-archive.com/jsmentors@jsmentors.com/
>
> To search via a non-Google archive, visit here:
> http://www.mail-archive.com/jsmentors@googlegroups.com/
>
> To unsubscribe from this group, send email to
> jsmentors+unsubscr...@googlegroups.com
>
> --
> To view archived discussions from the original JSMentors Mailman list:
> http://www.mail-archive.com/jsmentors@jsmentors.com/
>
> To search via a non-Google archive, visit here:
> http://www.mail-archive.com/jsmentors@googlegroups.com/
>
> To unsubscribe from this group, send email to
> jsmentors+unsubscr...@googlegroups.com
>
>
> --
> Lai, Yu-Hsuan
>
>
> --
> To view archived discussions from the original JSMentors Mailman list:
> http://www.mail-archive.com/jsmentors@jsmentors.com/
>
> To search via a non-Google archive, visit here:
> http://www.mail-archive.com/jsmentors@googlegroups.com/
>
> To unsubscribe from this group, send email to
> jsmentors+unsubscr...@googlegroups.com
>
>
>
>
> --
> To view archived discussions from the original JSMentors Mailman list:
> http://www.mail-archive.com/jsmentors@jsmentors.com/
>
> To search via a non-Google archive, visit here:
> http://www.mail-archive.com/jsmentors@googlegroups.com/
>
> To unsubscribe from this group, send email to
> jsmentors+unsubscr...@googlegroups.com
>



-- 
Lai, Yu-Hsuan

-- 
To view archived discussions from the original JSMentors Mailman list: 
http://www.mail-archive.com/jsmentors@jsmentors.com/

To search via a non-Google archive, visit here: 
http://www.mail-archive.com/jsmentors@googlegroups.com/

To unsubscribe from this group, send email to
jsmentors+unsubscr...@googlegroups.com

Reply via email to