数组中的'undefined'元素的JavaScript'in'运算符

请考虑下面的代码片段:

> 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 

我错过了什么吗? 这似乎是,根据我如何定义数组中undefined元素, in运算符的行为有所不同。

数组只是正常的JavaScript对象,有一些专业化。 从ECMA 5.1规范的“数组对象”部分引用

数组对象对特定类的属性名称给予特殊的处理。 当且仅当ToString(ToUint32(P))等于P且ToUint32(P)不等于2 32 -1时,属性名称P(以String值forms)才是数组索引

所以, 数组索引只是数组对象的属性 。 现在,让我们看看数组中缺less的元素。

从ECMA 5.1标准规范引用,

数组元素可能在元素列表的开始,中间或结束时被忽略。 只要元素列表中的逗号前面没有AssignmentExpression(即逗号在开头或逗号之后),缺less的数组元素将有助于数组的长度,并增加后续元素的索引。 数组元素没有被定义。 如果元素在数组末尾被消除,那么该元素不会影响数组的长度。

所以,当你说

 b = [1,,,,3]; 

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

你可以这样检查

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

只有指数04b 。 您可能想知道为什么a具有从04的属性,但值是undefined 。 因为指数1,2和3的元素被定义为undefined ,在b ,我们不知道这些值是什么。 这就是为什么他们没有分配到一个财产(索引)。

现在,你正在检查1是否在bin运算符中。 in运营商MDN Doc中引用,

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

所以,你基本上是检查1是否是b的属性之一,不是。 这就是为什么b '1'返回false

注意:

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

 console.log(a.indexOf(1)); # 0 console.log(b.indexOf(1)); # 0 console.log(b.indexOf(5)); # -1 

Array.prototype.indexOf返回-1如果被search的元素不在数组中。 所以,你可能想要做这样的事情

 console.log(a.indexOf(1) !== -1); # true console.log(b.indexOf(1) !== -1); # true console.log(a.indexOf(5) !== -1); # false 

在你的例子中,a [1]被定义,但是被设置为undefined ,因此1 in a == true 。 相反,b [1]完全没有设置,因此1 in b == false 。 这就是为什么有些人说undefined很奇怪。

要检查数组a是否具有 1,请使用a.indexOf(1) != -1

为了检查a[1]是否被定义,使用a.hasOwnProperty("1")1 in a是微妙不同的,可能实际上并不是你想要的,因为如果1被定义在a原型而不是在a本身)。

要将a[1]设置为undefined ,请使用a[1] = undefined

要定义a[1]停止,请使用delete a[1]

 //-1 means not in the list //['a','b','c'].indexOf('a') is return index if not find in the list then it give -1. if(['a','b','c'].indexOf('d') == -1) { console.log('yes it -1') }