Enthusiastic Developer
Enthusiastic Developer

Reputation: 762

Node.js v8 HOLEY arrays unexpected behavior

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

Answers (3)

Alnitak
Alnitak

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

Tejashwi Kalp Taru
Tejashwi Kalp Taru

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

jmrk
jmrk

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

Related Questions