Reputation: 762
After watching Mathias Bynens report about HOLEY and PACKED arrays, I did some experiments and got unexpected behavior. See two cases:
// CASE #1
const array = [0,1,2,3,4,5,undefined]
array.__proto__[6] = 'some value'
console.log(array[6]) // "some value" expected but got undefined
// CASE #2
const array = [0,1,2,3,4,5]
array[10] = 'faraway value'
array.__proto__[6] = 'some value'
console.log(array[6]) // "some value" expected and received
So, what the difference between these cases ? Why does in the first case it return undefined
without looking in the prototype chain ?
Upvotes: 2
Views: 281
Reputation: 339776
There's a distinction to be made between an undefined key, and an undefined value.
When you write const array = [ 0, undefined ]
you are creating a two element array where the second index (1) has a value of undefined.
If instead you write const array = [ 0, , ]
you are still creating a two element array but it is now sparse and the second index (or "key") doesn't even exist, even though it is less than the array's .length
property.
Since there's no key, the interpreter will check in the prototype instead.
Upvotes: 0
Reputation: 3064
What happens in your case 1
const array = [0,1,2,3,4,5,undefined] //array length is 7
array.__proto__[6] = 'some value' //will not work becasue 6th position already exists and JS will not load it from proto chain
console.log(array[6]) // you will get undefined because you assigned undefined at 6th position
In your case 2
const array = [0,1,2,3,4,5] //length 6
array[10] = 'faraway value' //you added value on position 10, hence values between 6 and 10 is empty
array.__proto__[6] = 'some value' // you pushed value on position 6 using proto
console.log(array[6]) // you will get some value because position 6 is empty and hence JS tried to look into proto chain
So what basically you can say is, __proto__
assignment will only work if the assigned position is empty, and hence if the position is empty then JS will lookup in the proto chain.
So,
if array[6]
exists then array.__proto__[6] = 'value'
will not work or change the value of existing array[6]
value, but if array[6]
is empty then doing array.__proto__[6] = 'value'
and getting it will work
A side note, using __proto__
is deprecated.
Upvotes: 0
Reputation: 40491
In case #1, you're explicitly putting undefined
into the array. There is no need to go up the prototype chain because the element is present. Compare:
var case1 = [0, 1, 2, 3, 4, 5, undefined, 7];
var case2 = [0, 1, 2, 3, 4, 5, , 7];
case1.hasOwnProperty(6); // true
case2.hasOwnProperty(6); // false
console.log(case1[6]); // "undefined", loaded from object
console.log(case2[6]); // "undefined", because no element was found (not on the object, and not on the prototype chain)
case2.__proto__[6] = "proto value";
console.log(case2[6]); // "proto_value", loaded from prototype chain
Upvotes: 2