在哪些情况下 val !== val? (将变量与自身进行比较)

In which cases val !== val? (compare a variable with itself)

我只是在创建一个函数,它将 JSON.stringify 一个输入,但也会检测 NaN 数字输入,但不想使用 typeof,原因如下所述.输入可以是 numberbooleanstring。仅此而已。

我已经达到了NaN !== NaN的情况,所以:

if (input !== input || input === Infinity || input === -Infinity) {
    output = input.toString();
} else {
    output = JSON.stringify(input);
}

我这样做是因为 JSON.stringify() returns "null" 当值为 NaNInfinity.

我知道使用 typeoftoString() 这很容易实现,但是一些性能测试表明 typeof 在 IE11 下真的很慢(比 IE11 慢 4-5 倍) JSON.stringify()在我们的情况下),这里需要重点关注IE11。

我想知道有没有更多的情况val !== val.

这里有一个性能测试:https://jsperf.com/typeof-vs-nan-nan2 没有使用 SO 一个,因为它们似乎 运行 编码服务器端,因为那里的 IE 性能与其他地方一样好。不可能的事。

本地测试是:

var mockdata = [];

function notToJson(val) {
    return val !== val || val === Infinity || val === -Infinity;
}

for (var i = 0; i < 500000; i++) {
    var n = Math.floor(Math.random()*1000000);
    if (Math.random()>0.5) {
        n = n.toString();
    } else if (Math.random()>0.5) {
        if (Math.random()>0.5) {
            n = NaN;
        } else {
            if (Math.random()>0.5) {
                n = Infinity;
            } else {
                n = -Infinity;
            }
        }
    }
    mockdata.push(n);
}

console.time("typeof");
for (i = 0; i < 500000; i++) {
    var res = typeof mockdata[i] === "string";
}
console.timeEnd("typeof");

console.time("notToJson");
for (i = 0; i < 500000; i++) {
    res = notToJson(mockdata[i]);
}
console.timeEnd("notToJson");

console.time("toString");
for (i = 0; i < 500000; i++) {
    res = mockdata[i].toString();
}
console.timeEnd("toString");

console.time("JSON.stringify");
for (i = 0; i < 500000; i++) {
    res = JSON.stringify(mockdata[i]);
}
console.timeEnd("JSON.stringify");

console.time("Full typeof");
for (i = 0; i < 500000; i++) {
    res = typeof mockdata[i]==="string"?JSON.stringify(mockdata[i]):mockdata[i].toString();
}
console.timeEnd("Full typeof");

console.time("Full notToJson");
for (i = 0; i < 500000; i++) {
    res = notToJson(mockdata[i])?mockdata[i].toString():JSON.stringify(mockdata[i]);
}
console.timeEnd("Full notToJson");

Chrome 输出为:

但是 IE11 输出是:

我注意到 mockdata 的字符串越少,typeof 的性能明显提高(谈论 IE11)。

以下是 val !== val returns 正确的一些情况:

console.log({} !== {}); // true
console.log(new Date() !== new Date()); // true
console.log(new String("") !== new String("")); // true

仅当对象不同时适用:

var a = b = {}; // now they are equal
console.log(a !== b); // false

它也发生在 Symbols(ES6 特性):

console.log(Symbol() !== Symbol()); // true

我要自己回答这个问题,因为我不喜欢没有答案的问题。

请注意问题是如何谈论 val 的。我的意思是给一个变量赋值,然后比较变量和它自己不要创建两个不同的变量并比较它们。

根据我自己的测试,val !== val仅当val = NaN时,所以:

var val = NaN;
console.log("val !== val:", val !== val);

原因就在这里:Why is NaN not equal to NaN?