javascriptobjectprototypal-inheritanceshadowing

Property Shadowing Issue


I'm learning JS. Kyle Simpson in his Book, YDKJS, writes that:

If a normal data accessor (see Chapter 3) property named foo is found anywhere higher on the [[Prototype]] chain, and it's not marked as read-only ( writable:true) then a new property called foo is added directly to myObject , resulting in a shadowed property.

function Foo(name) {
this.name = name;
}
Foo.prototype.myName = function() {
return this.name;
};
var a = new Foo( "a" );
var b = new Foo( "b" );

In the above snippet, it's strongly tempting to think that when a and b are created, the properties/functions on the Foo.prototype object are copied over to each of a and b objects. However, that's not what happens. When myName is not found on a or b , respectively, it's instead found (through delegation, see Chapter 6) on Foo.prototype . Reference Page 97

To test the same, I created a property val on prototype object with value 1:

Foo.prototype.val = 1;

Since object a is prototype linked, I incremented this property by 1:

a.val++;

But when I executed following two lines:

console.log(a.val);   
console.log(Foo.prototype.val);   

Result:

2
1

The result shows that a separate property val is created on object a with the incremented value 2, which seems contradicts (that its delegated) with his statement.

Where did I astray? Please guide


Solution

  • I think you may be confusing what happens with values on the prototype when assigning a value vs when creating an object using the constructor function.

    For example, take the book's first example:

    Foo.prototype.myName = function() {...};
    var a = new Foo( "a" );
    var b = new Foo( "b" );
    

    As Kyle outlines in his book, when using the new keyword to create objects a and b, the values from Foo.prototype aren't created as properties directly on a and b (ie: own-properties), but instead, a and b's [[Prototype]]s point to Foo.prototype, which is where myName is accessed.

    In your example code, you're firstly creating a property called val on the prototype:

    Foo.prototype.val = 1;
    

    and then incrementing val. This increment is what then creates an own-property on a. To show what's happening in more detail, the below is begin performed:

     v--- creates an own-property directly on `a` 
    a.val = a.val + 1;
             ^--- accessing 1 from `Foo.prototype.val`
    

    The a.val = component of the above creates an own property called val directly on the a object, and the a.val + 1 is accessing the value you had previously set with Foo.prototype.val = 1; via accessing a via the [[Prototype]], and then adding 1 to it. As you're effectively doing an "assignment" here, you end up creating an own property on a, which is a different operation from what the excerpt shown from Kyle's book is doing, where he is just creating a new object using the new keyword.