Yos*_*ein 133 javascript arrays nan ecmascript-6
我熟悉的NaN
是在JavaScript中“怪异”的,即NaN === NaN
总是返回false
,如所描述这里。因此,不应通过===
比较来检查NaN
,而应使用 isNaN(..) 。
所以我惊讶地发现
> [NaN].includes(NaN)
true
Run Code Online (Sandbox Code Playgroud)
这似乎不一致。为什么会有这种行为?
它是如何工作的?请问includes
方法专门检查isNaN
?
Ngu*_*ong 144
根据MDN 的文档说
注意:从技术上讲,
includes()
使用sameValueZero
算法来确定是否找到给定元素。
const x = NaN, y = NaN;
console.log(x == y); // false -> using ‘loose’ equality
console.log(x === y); // false -> using ‘strict’ equality
console.log([x].indexOf(y)); // -1 (false) -> using ‘strict’ equality
console.log(Object.is(x, y)); // true -> using ‘Same-value’ equality
console.log([x].includes(y)); // true -> using ‘Same-value-zero’ equality
Run Code Online (Sandbox Code Playgroud)
Object.is()
和===
是在他们的治疗符号零和NaN的。You*_*saf 25
该.includes()
方法使用SameValueZero
算法来检查两个值的相等性,并认为该NaN
值等于自身。
的SameValueZero
算法类似于SameValue
,但唯一的区别是,SameValueZero
算法考虑+0
和-0
是相等的。
该Object.is()
方法使用SameValue
并为 返回 true NaN
。
console.log(Object.is(NaN, NaN));
Run Code Online (Sandbox Code Playgroud)
.includes()
方法的行为与方法略有不同.indexOf()
;该.indexOf()
方法使用严格相等比较来比较值,严格相等比较不认为NaN
等于自身。
console.log([NaN].indexOf(NaN));
Run Code Online (Sandbox Code Playgroud)
可以在 MDN 上找到有关不同相等性检查算法的信息:
VLA*_*LAZ 19
这似乎是Number::sameValueZero
抽象操作的一部分:
6.1.6.1.15 Number::sameValueZero ( x , y )
- 如果x是NaN并且y是NaN,则返回true。
[...]
此操作是Array#includes()
检查的一部分,它执行以下操作:
22.1.3.13 Array.prototype.includes ( searchElement [ , fromIndex ] )
[...]
- 重复,而k < len
a。让elementK是 ? Get( O , !ToString( k ))。
湾 如果 SameValueZero( searchElement , elementK ) 为true,则返回true。
C。将 k 设置为 k + 1。- 返回false。
[...]
当SameValueZero
操作将委托给一个在步骤2的数字:
7.2.12 SameValueZero ( x , y )
[...]
- 如果 Type( x ) 与 Type( y ) 不同,则返回false。
- 如果 Type( x ) 是 Number 或 BigInt,则
a. 返回 !类型( x )::sameValueZero( x , y )。- 返回 !SameValueNonNumeric( x , y )。
对于比较Array#indexOf()
将使用严格相等比较,这就是为什么它的行为不同:
const arr = [NaN];
console.log(arr.includes(NaN)); // true
console.log(arr.indexOf(NaN)); // -1
Run Code Online (Sandbox Code Playgroud)
SameValueZero
用于比较的其他操作在集合和映射中:
const s = new Set();
s.add(NaN);
s.add(NaN);
console.log(s.size); // 1
console.log(s.has(NaN)); // true
s.delete(NaN);
console.log(s.size); // 0
console.log(s.has(NaN)); // false
Run Code Online (Sandbox Code Playgroud)
const m = new Map();
m.set(NaN, "hello world");
m.set(NaN, "hello world");
console.log(m.size); // 1
console.log(m.has(NaN)); // true
m.delete(NaN);
console.log(m.size); // 0
console.log(m.has(NaN)); // false
Run Code Online (Sandbox Code Playgroud)
该SameValueZero
算法首先出现在 ECMAScript 6 规范中,但它更加冗长。它仍然具有相同的含义,并且仍然具有明确的含义:
7.2.10 SameValueZero( x , y )
[...]
- 如果 Type( x ) 是 Number,则 a. 如果x是NaN并且y是NaN,则返回true。[...]
ECMAScript的5.1只有一个SameValue
算法仍对待NaN
等于NaN
。唯一有区别SameValueZero
的是如何+0
和-0
对待:SameValue
回报false
他们,而SameValueZero
回报true
。
SameValue
多用于内部对象操作,因此对于编写JavaScript代码几乎无关紧要。的很多用途SameValue
是在使用对象键并且没有数字值时。
该SameValue
操作直接在 ECMAScript 6 中公开,因为它Object.is()
使用的是:
console.log(Object.is(NaN, NaN)); // true
console.log(Object.is(+0, -0)); // false
Run Code Online (Sandbox Code Playgroud)
稍微值得关注的是,WeakMap
与WeakSet
同样使用SameValue
,而不是SameValueZero
说Map
和Set
使用进行比较。但是,WeakMap
并且WeakSet
只允许对象作为唯一成员,因此尝试添加NaN
或+0
或-0
或其他原语会导致错误。
在7.2.16 Strict Equality Comparison 中,有如下注释:
笔记
该算法在处理有符号零和 NaN 方面与SameValue算法不同。
这意味着对于Array#includes
与严格比较不同的比较函数:
22.1.3.13 Array.prototype.includes下面
注 3
在包括方法有意地从类似的不同的indexOf以两种方式的方法。首先,它使用SameValueZero算法,而不是Strict Equality Comparison,允许它检测NaN数组元素。其次,它不会跳过丢失的数组元素,而是将它们视为undefined。
归档时间: |
|
查看次数: |
9427 次 |
最近记录: |