JavaScript'in'运算符用于Arrays中的`undefined`元素

fcr*_*r79 18 javascript arrays

请考虑以下代码段:

> a = [1, undefined, undefined, undefined, 3]
  [1, undefined, undefined, undefined, 3]
> b = [1,,,,3]
  [1, undefined × 3, 3]
> 1 in a
  true
> 1 in b
  false
Run Code Online (Sandbox Code Playgroud)

我错过了什么吗?似乎是,根据我undefined在数组中定义元素的方式,in运算符的行为会有所不同.

the*_*eye 31

数组只是普通的JavaScript对象,只有一些特殊化.引用ECMA 5.1规范的"数组对象"部分

数组对象对特定类的属性名称进行特殊处理.当且仅当ToString(ToUint32(P))等于P且ToUint32(P)不等于2 32 -1时,属性名P(以String值的形式)是数组索引.

因此,数组索引只是数组对象的属性.现在,让我们看一下Array中缺少的元素.

引用ECMA 5.1标准规范,

可以在元素列表的开头,中间或末尾省略数组元素.每当元素列表中的逗号前面没有AssignmentExpression(即开头的逗号或另一个逗号后面的逗号)时,缺少的数组元素会增加数组的长度并增加后续元素的索引.未定义Elided数组元素.如果在数组的末尾省略了元素,则该元素不会影响数组的长度.

所以,当你说的时候

b = [1,,,,3];
Run Code Online (Sandbox Code Playgroud)

除了元素1和3之外,所有其他元素都被视为数组中的缺失元素.现在元素13对应的属性04(数组索引以0JavaScript 开头).

你可以这样检查一下

console.log(Object.getOwnPropertyNames(b));
# [ '0', '4', 'length' ]
console.log(Object.getOwnPropertyNames(a));
# [ '0', '1', '2', '3', '4', 'length' ]
Run Code Online (Sandbox Code Playgroud)

只有指数0并且4b.你可能会奇怪,为什么a具有从属性04,虽然值undefined.因为,索引1,2和3 undefined的元素被定义为,在这里b,我们不知道这些值是什么.这就是为什么它们没有分配给属性(索引).

现在,您正在与操作员一起检查是否1在.从运营商MDN Doc引用,binin

如果指定的属性在指定的对象中,则in运算符返回true.

所以,你基本上1是在检查是否是其中一个属性b,而不是.这就是为什么'1'b收益false.

注意:

如果你想知道是否1在数组中,你应该Array.prototype.indexOf像这样使用

console.log(a.indexOf(1));
# 0
console.log(b.indexOf(1));
# 0
console.log(b.indexOf(5));
# -1
Run Code Online (Sandbox Code Playgroud)

Array.prototype.indexOf返回-1如果被搜索的元素是不存在的数组.所以,你可能想做这样的事情

console.log(a.indexOf(1) !== -1);
# true
console.log(b.indexOf(1) !== -1);
# true
console.log(a.indexOf(5) !== -1);
# false
Run Code Online (Sandbox Code Playgroud)

  • 我认为你的**Note**是最重要的部分.OP似乎在寻找**值**,但实际上是在寻找**键**,使用错误的东西(`in`运算符,而不是`[] .indexOf`)...也许不是 (6认同)
  • 对我来说最重要的部分似乎是"定义为'未定义'"的概念 - 很多人似乎都错过了这种区别. (5认同)