1

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...

Djorren
  • 21
  • 3
  • If you read the description of [Object.prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype), you can see that Object.setPrototypeOf(t1, t2) overrides prototype completely. So what you are doing should not cause amazement. That is the general behaviour. – Shaurya Dhadwal Aug 01 '18 at 12:02
  • That is not what I am addressing here. The amazement is that defining y at the base object using t1.y = 100 does not add the property to t1. using Object.defineProperty does add y to t1 – Djorren Aug 01 '18 at 12:11
  • 1
    Making it non-writable and non-configurable on `t2` doesn't make it non-shadowable. Yes, the assignment takes the writability of inherited properties into account, but `Object.defineProperty` doesn't. – Bergi Aug 01 '18 at 12:59

1 Answers1

0

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 });
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Keith
  • 22,005
  • 2
  • 27
  • 44