0

All, After reading this post, and did some test based on it .

        function Shape() {
            this.x = 0;
            this.y = 0;
        };

        Shape.prototype.move = function(x, y) {
            this.x += x;
            this.y += y;
            console.log("Shape moved.");
        };

        // Rectangle - subclass
        function Rectangle() {
            //Shape.call(this); //call super constructor.
        };

        Rectangle.prototype = Object.create(Shape.prototype);

        var rect = new Rectangle();
                    alert(rect.x);

If I commented the code Shape.call(this); in the Rectangle, I found the rect.x is underfined instead of the value 0.

And What make me confused is that I found in the best answer of the Post said:

"In javascript, every object has a secret link to the object which created it,forming a chain. When an object is asked for a property that it does not have,its parent object is asked... continually up the chain until the property is found or until the root object is reached."

So I can't understand why the rect can't found x in the prototype chain. The rect is already inherited form Shape. If the x doesn't exist in the rect, It supposed be found in his parent. right ? And in my understanding .If using Shape.call(this); , It just add a new x property to the rect, well ,that would not be a code reusing the original x from parents. It just like the override property in the classical inheritance . that is add a new property into the sub class which have the same name and type as the one in the base class..I don't know if my understanding is right , if not . please correct me .Or was I missing something I didn't noticed ? thanks.

Edit

Below is my understanding based on the Thilo and Arun P Johny 's answers. please correct me if it is not right.

Before inheritance happen.

enter image description here

After inheritance executed.

enter image description here

So the x only belong to the instance constructed by Shape. thanks

Community
  • 1
  • 1
Joe.wang
  • 11,537
  • 25
  • 103
  • 180

2 Answers2

1

If you don't call the super constructor, then this.x = 0 is not executed so x remains undefined.

If you wanted it to appear in the prototype, you'd have to say Shape.prototype.x = 0, I think.

So I can't understand why the rect can't find x in the prototype chain.

It's because the prototype does not have x either. It only has move. The x gets assigned to individual instances in the constructor (but only if you call it).

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • Friend , I am also in china. If do so , I think That is a new `x` distinct from the `x` in the super object ... Is it against OOP inheritance ? – Joe.wang Apr 21 '13 at 08:45
  • If you want inheritance to work "all the way" you probably have to call the super constructors. – Thilo Apr 21 '13 at 08:46
  • 3
    In prototypical inheritance, constructors are not inherited, only prototypical values are inherited – Arun P Johny Apr 21 '13 at 08:46
  • If you want to copy the constructor then you may have to call `Shape.call(this)` inside `Rectangle` constructor as you have done(but commented) – Arun P Johny Apr 21 '13 at 08:48
  • Hi , Guys ,Could you please verify my updated? I updated it based your kindly answers and comments. – Joe.wang Apr 21 '13 at 09:07
1

Arun P Johny is right (you should read his comment!)

Try this:

    function Shape() {
        this.x = 0;
        this.y = 0;
    };

    Shape.prototype.move = function(x, y) {
        this.x += x;
        this.y += y;
        console.log("Shape moved.");
    };


    // Rectangle - subclass
    function Rectangle() {            
    };

    Rectangle.prototype = new Shape();
    var rect = new Rectangle();
    alert(rect.x);

You can call Shape.call(this); like you did (commented) in your code, but this way it's not a "real" inheritance since you won't be able to use move() in Rectangle.

But the code above is a mishmash of "new" and prototypes and hence very confusing. I guess that what you really want to do is something like this:

   var Shape = {
        x: 0,
        y: 0,
        move: function(x, y) {
            this.x += x;
            this.y += y;
            alert("Shape moved: ["+this.x+","+this.y+"]");
        }
    };

    var rect = Object.create(Shape);
    alert(rect.x);
    rect.move(2,3);
    rect.move(1,1);
Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
  • Yes, I think the most valuable comments is `In prototypical inheritance, constructors are not inherited, only prototypical values are inherited`. – Joe.wang Apr 21 '13 at 09:11
  • I think that the word "prototype" might be a litle bit confusing: Prototypal inheritance is when one object inherits the properties of another object - no classes are involved (hence no constructor) - there is no "template" that creates objects! – Nir Alfasi Apr 21 '13 at 09:12
  • I see. except when `call(this)`. – Joe.wang Apr 21 '13 at 09:15
  • I didn't understand your last comment – Nir Alfasi Apr 21 '13 at 09:16
  • :) forget about it . What I understand from your comment `no template` means the object initialized state is `{}` no matter what object it is inherited from, right ? – Joe.wang Apr 21 '13 at 09:21
  • no that's not what I said. A "template" is another way to describe a "class". If your "class" is `function Rectangle() {}` then yes - the object's initial state is empty. – Nir Alfasi Apr 21 '13 at 09:39
  • calling `Rectangle.prototype = Shape.prototype;` or `Rectangle.prototype = new Shape();` allows Rectangle to adopt all the properties of Shape. – Nir Alfasi Apr 21 '13 at 09:40
  • It looks very flexible...:) – Joe.wang Apr 21 '13 at 09:43
  • I think that it'll be easier to grasp if you'll have a look on the second code example I just posted. – Nir Alfasi Apr 21 '13 at 10:02
  • hm...Actually, I am trying to find a best practice of implement inheritance :) – Joe.wang Apr 21 '13 at 10:15
  • Since JS is a prototypical language, I believe that the best practice is using Prototypal inheritance. – Nir Alfasi Apr 21 '13 at 10:18
  • Yes, you know , The difficulty of it is how to make the code elegant and accessible. – Joe.wang Apr 21 '13 at 10:23
  • Well, I find the second code example I added here very elegant - it's Douglas Crockford style ;) – Nir Alfasi Apr 21 '13 at 16:57
  • friend, @alfasin, one of shortcomings I can find in your second code example is can not `new` a `rect`, that means there is no constructor for object initialization. It will make the initialization code looks not elegant. So I think the code I post is better one. all the initialization code is in the constructor. :) – Joe.wang Apr 22 '13 at 07:07
  • The original link is [here](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create). – Joe.wang Apr 22 '13 at 07:15
  • 1
    If you're going to use JS intensively, I highly recommend on reading this: http://javascript.crockford.com/prototypal.html and: http://stackoverflow.com/a/2709811/1057429 – Nir Alfasi Apr 22 '13 at 18:00
  • :) I don't know why ,I just prefer to the code looks more like in a traditional style. but in essence, Javascript is a prototype based programming language which is different from the classical based programming language. – Joe.wang Apr 23 '13 at 01:57