【问题标题】:In which cases val !== val? (compare a variable with itself)在哪些情况下 val !== val? (将变量与自身进行比较)
【发布时间】:2017-07-09 18:54:13
【问题描述】:

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

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

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

我这样做是因为JSON.stringify() 在值为NaNInfinity 时返回"null"

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

【问题讨论】:

  • 原因是IE11速度慢,你可以在问题中读到。
  • @George——但这是针对不同的对象。
  • 请使用&lt;&gt; sn-p 编辑器发布minimal reproducible example
  • @George——但它们是两个不同的值。 OP 正在寻找的是当一个值不等于自身时,var a = {}; a === a 为真,但var b = NaN; b === b 为假。
  • 使用Number.isNaN?当使用 JSON.stringify 时,typeof 真的那么慢吗? PS:还有更深奥的情况,在某种程度上,val !== val。我能想到的一种结构是在查找之间执行任何类型的代码时,例如对于 getter、隐式 valueOf 调用等。

标签: javascript types nan


【解决方案1】:

以下是val !== val 返回 true 的一些情况:

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

【讨论】:

  • 所有这些都是不同的对象,如 cmets 中所述。注意val !== val 中的val。我想给一个变量赋值并检查那个变量。
【解决方案2】:

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2021-12-17
    • 2021-06-09
    • 1970-01-01
    • 2014-09-01
    • 2015-01-24
    • 1970-01-01
    • 2013-01-05
    相关资源
    最近更新 更多