3

我正在阅读权威指南 Javascript,并遇到了一段话,我引用了

如果您使用恰好是非负整数的字符串对数组进行索引,则它表现为数组索引而不是对象属性

所以类似的东西a["4"]会存储在索引 5 中,而类似的东西a["-1.26"]会被存储为属性"1.26"..

我有点冒险并尝试了a["02"] = 2; 现在我可以设置它,检索它,但它既没有设置为a[2](基本上a[parseInt("02")]),也没有在我打印数组时得到它..

这是我的代码。我用节点和浏览器试了一下。

> a[3] = 3;
3
> a["-1.2"] = 10;
10
> a
[ , , , 3, '-1.2': 10 ]
> a["02"] = 2;
2
> a
[ , , , 3, '-1.2': 10 ]
> a["02"]
2
> a.length
4

我只是想了解到底发生了什么。

4

3 回答 3

3

从规格

当且仅当 ToString(ToUint32(P)) 等于 P 且 ToUint32(P) 不等于 2^32-1 时,属性名称 P(以字符串值的形式)是数组索引。

所以这本书具有误导性,因为它必须是一个整数,没有前导零等。

所以"02"被视为"hellokitty"- 在任何意义上都不是索引属性。

考虑 :

var P = "02"
console.log( ( P ) === ( ( +P >>> 0 ).toString() ) );
//false

var P = "2"
console.log( ( P ) === ( ( +P >>> 0 ).toString() ) );
//true

这是一个函数

function isStringConsideredArrayIndex( P ) {
    if( typeof P !== "string" ) throw new Error( "strings only" );
    return ( (P >>> 0).toString() ) === P && 
        ( P >>> 0 ) !== ( Math.pow( 2, 32 ) - 1 );
}
于 2013-08-11T17:46:31.873 回答
1

要知道的主要事情是,您的“数组”实际上更像是一张地图(有一些例外);

a = {}; // a is an empty object
a['02'] = 'foo';
a['2'] = 'bar';
console.log( a ); // { '02': 'foo', '2': 'bar' }

如果是一个数组,这同样适用a,只是它的打印方式可能不同。例如,谷歌浏览器只会打印数组对象的类似数组的键(所以在这种情况下你会看到[undefined, undefined, 'bar']. 它仍然具有其他属性,但它的“打印功能”需要一个更好的术语只是显示数组- 类似的。

还有其他差异。数组具有某些属性,例如length(将等于您定义的最大数字索引 + 1)和各种操作函数('pop'、'join' 等)。

正如已经指出的那样,如果索引可以无损地转换为无符号整数,则它被认为是类似数字的。ie"2" -> 2 -> "2"什么都不损失,而"02" -> 2 -> "2"失去领先0

要查看对象或数组中所有内容的完整列表,您可以使用它(这将显示您丢失的“02”键):

for(var i in a){
    console.log(i,a[i])
}
于 2013-08-11T17:39:13.867 回答
0

在内部,JavaScript 将在数组索引设置之前对它们运行以下函数:

    function ToUint32(x) {
        return x >>> 0;
    }

因此,只有数字或数字字符串才是有效的数组索引。

索引也必须在以下范围内 [0, 2^32−1]。

如果一个字符串不是数字,则默认返回对象键。

于 2013-08-11T17:38:19.520 回答