数组中“未定义”元素的 JavaScript 'in' 运算符

IT技术 javascript arrays
2021-02-09 02:49:51

请考虑以下代码片段:

> 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运算符的行为有所不同。

3个回答

数组只不过是普通的 JavaScript 对象,具有一些特殊性。引用ECMA 5.1 规范的数组对象部分

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

因此,数组索引只不过是数组对象的属性现在,让我们看看数组中缺少的元素。

引自ECMA 5.1 标准规范

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

所以,当你说

b = [1,,,,3];

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

你可以像这样检查

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

只有索引04在 中b您可能想知道为什么a属性从04,尽管值是undefined因为,索引 1、2 和 3 处的元素被定义为undefined,而在 中b,我们不知道这些值是什么。这就是为什么它们没有分配给属性(索引)的原因。

现在,您正在使用运算符检查是否1b, 中in引自in运营商 MDN Doc

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

因此,您基本上1是在检查 if是 的属性之一b,而不是。这就是为什么'1'inb回报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如果被搜索的元素是不存在的数组。所以,你可能想做这样的事情

console.log(a.indexOf(1) !== -1);
# true
console.log(b.indexOf(1) !== -1);
# true
console.log(a.indexOf(5) !== -1);
# false
对我来说,最重要的部分似乎是“定义为undefined的概念——很多人似乎都忽略了这种区别。
2021-03-18 02:49:51
@NiettheDarkAbsol 所说的,用我的话来说 - 已定义、未定义和未声明之间的区别。在这种,,,情况下,位置 1 的元素被视为未声明。没有具有该名称的属性。
2021-03-24 02:49:51
我认为你的笔记是最重要的部分。OP 似乎正在寻找,但实际上是通过使用错误的东西(运算符,而不是搜索......虽然可能不是in[].indexOf
2021-04-12 02:49:51

在您的示例中, 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略有不同,实际上可能不是您想要的,因为如果1a的原型中定义而不是在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')
}