Node.js v8 HOLEY 数组意外行为
Node.js v8 HOLEY arrays unexpected behavior
看完 Mathias Bynens 关于 HOLEY 和 PACKED 数组的报告后,我做了一些实验并得到了意想不到的行为。看两种情况:
// 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
那么,这些案例之间有什么区别?为什么在第一种情况下 return undefined
没有查看原型链?
在案例 #1 中,您明确地将 undefined
放入数组中。没有必要沿着原型链往上走,因为元素已经存在。比较:
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
你的情况 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
你的情况 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
所以基本上你可以说的是,__proto__
赋值只有在分配的位置为空时才会起作用,因此如果位置为空,那么 JS 将在原型链中查找。
所以,
如果 array[6]
存在,则 array.__proto__[6] = 'value'
将不起作用或更改现有 array[6]
值的值,但如果 array[6]
为空,则执行 array.__proto__[6] = 'value'
并获取它将会起作用
旁注,使用 __proto__
是 deprecated。
未定义的 key 和未定义的 value.
是有区别的
当您编写 const array = [ 0, undefined ]
时,您正在创建一个双元素数组,其中第二个索引 (1) 的 value 未定义。
如果你写 const array = [ 0, , ]
你仍然在创建一个双元素数组,但它现在是 sparse 并且第二个索引(或 "key")没有' 甚至存在,即使它小于数组的 .length
属性.
由于没有密钥,解释器将改为签入原型。
看完 Mathias Bynens 关于 HOLEY 和 PACKED 数组的报告后,我做了一些实验并得到了意想不到的行为。看两种情况:
// 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
那么,这些案例之间有什么区别?为什么在第一种情况下 return undefined
没有查看原型链?
在案例 #1 中,您明确地将 undefined
放入数组中。没有必要沿着原型链往上走,因为元素已经存在。比较:
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
你的情况 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
你的情况 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
所以基本上你可以说的是,__proto__
赋值只有在分配的位置为空时才会起作用,因此如果位置为空,那么 JS 将在原型链中查找。
所以,
如果 array[6]
存在,则 array.__proto__[6] = 'value'
将不起作用或更改现有 array[6]
值的值,但如果 array[6]
为空,则执行 array.__proto__[6] = 'value'
并获取它将会起作用
旁注,使用 __proto__
是 deprecated。
未定义的 key 和未定义的 value.
是有区别的当您编写 const array = [ 0, undefined ]
时,您正在创建一个双元素数组,其中第二个索引 (1) 的 value 未定义。
如果你写 const array = [ 0, , ]
你仍然在创建一个双元素数组,但它现在是 sparse 并且第二个索引(或 "key")没有' 甚至存在,即使它小于数组的 .length
属性.
由于没有密钥,解释器将改为签入原型。