Search code examples
javascriptprototypedefineproperty

Adding properties in prototype chains using DefineProperty


I found a difference in how JavaScript adds properties to objects. Code example below shows it.

var t1 = {
    x: 1
}

var t2 = {}

Object.defineProperty(t2, 'y', {
    value: 2,
    configurable: false,
    writable: false
});

Object.setPrototypeOf(t1, t2);

t1.y = 100;
t1.y; --> returns 2
Object.defineProperty(t1, 'y', { value: 100 });
t1.y; --> return 100

t1 has t2 as its prototype. I make sure the property 'y' added to t2 is non configurable and non writable. When I try to add y to t1 by using t1.y = 100, y is not added to the object and t1.y still return 2. However, when using defineProperty, y does get added to t1.

I figure it has something to do with how JavaScript treats the prototype chain but i can't wrap my head around it...


Solution

  • What will make this easier to understand is if we look at what t1 and t2 look like..

    Before we do any assigning.

    t1 = { x: 1 } -> proto { y: 2 }
    t2 = { y: 2 }
    

    Now we try assigning 100 to t1.y..
    Now y is found on t1's prototype that has the defineProperty on, so 100 is ignored, or error in strict mode.

    Now what happens when we do define property on t1.

    t1 = { x: 1, y: 100 } -> proto { y: 2 }
    t2 = { y: 2 }
    

    IOW: your defineProperty is actually applied to a different object, and now due to the way property lookup works, y = 100 is found first. If you tried to defineProperty on the same object, like below, it would fail.

    Object.defineProperty(Object.getPrototypeOf(t1), 'y', { value: 100 });