在 JavaScript 比较中应该使用哪个等号运算符(== vs ===)?

Posted

技术标签:

【中文标题】在 JavaScript 比较中应该使用哪个等号运算符(== vs ===)?【英文标题】:Which equals operator (== vs ===) should be used in JavaScript comparisons? 【发布时间】:2010-09-26 10:43:47 【问题描述】:

我正在使用 JSLint 浏览 javascript,并且在执行比较 idSele_UNVEHtype.value.length == 0if 声明。

=== 替换== 是否有性能优势?

任何性能改进都会受到欢迎,因为存在许多比较运算符。

如果不进行类型转换,是否会比== 获得性能提升?

【问题讨论】:

【参考方案1】:

这是===== 之间相等比较的有趣可视化。

来源:https://github.com/dorey/JavaScript-Equality-Table(demo,unified demo)


var1 === var2

当使用=== 进行 JavaScript 相等性测试时,一切都保持原样。 在评估之前没有任何东西被转换。

var1 == var2

当使用 == 进行 JavaScript 相等性测试时,会发生一些时髦的转换

Javascript 中的相等性总结


结论:

除非您完全理解与== 发生的funky conversions,否则请始终使用===

【讨论】:

更好的 '==' 表:algassert.com/visualization/2014/03/27/… 至少 == 比较是可交换的(即 (a==b) === (b==a))XD【参考方案2】:

根据经验,我通常会使用=== 而不是==(以及!== 而不是!=)。

上面的答案中解释了原因,Douglas Crockford 也很清楚 (JavaScript: The Good Parts)。

但是有一个例外== null 是检查“为空或未定义”的有效方法:

if( value == null )
    // value is either null or undefined

例如 jQuery 1.9.1 使用这种模式 43 次,JSHint syntax checker 甚至为此提供了eqnull 放松选项。

来自jQuery style guide:

应该使用严格的相等检查 (===) 来支持 ==。唯一的 例外是通过 null 检查 undefined 和 null。

// Check for both undefined and null values, for some important reason. 
undefOrNull == null;

编辑 2021-03:

现在most browsers 支持Nullish coalescing operator (??) 和Logical nullish assignment (??=),它允许更简洁的方式 如果变量为 null 或未定义,则分配默认值,例如:

if (a.speed == null) 
  // Set default if null or undefined
  a.speed = 42;

可以写成这些形式中的任何一种

a.speed ??= 42;
a.speed ?? a.speed = 42;
a.speed = a.speed ?? 42;

【讨论】:

== null 是检查‘是null 还是undefined’的有效方法” ... or document.all【参考方案3】:

简单

== 表示操作数之间的比较具有类型强制

=== 表示操作数之间的比较没有类型强制。

JavaScript 中的类型强制意味着自动将数据类型转换为其他数据类型。

例如:

123 == "123"  // Returns true, because JS coerces string "123" to number 123
              // and then goes on to compare `123 == 123`.

123 === "123" // Returns false, because JS does not coerce values of different types here.

【讨论】:

【参考方案4】:

我在 Firefox 中使用Firebug 使用如下代码对此进行了测试:

console.time("testEquality");
var n = 0;
while (true) 
  n++;
  if (n == 100000)
    break;

console.timeEnd("testEquality");

console.time("testTypeEquality");
var n = 0;
while (true) 
  n++;
  if (n === 100000)
    break;

console.timeEnd("testTypeEquality");

我的结果(每次测试五次并取平均值):

==: 115.2
===: 114.4

所以我会说微小的差异(这是超过 100000 次迭代,请记住)可以忽略不计。性能不是=== 的理由。类型安全(嗯,和你在 JavaScript 中一样安全)和代码质量。

【讨论】:

现在,当== 运算符存在实际类型强制时,它们如何比较?请记住,这就是性能提升的时候。 正确测试时的主要区别是上述原因更快地只检查类型不等式。 jsfiddle.net/4jhuxkb2【参考方案5】:

== 运算符只比较值而不是数据类型。

=== 运算符将值与其数据类型进行比较。

例如:

1 == "1" //true

1 === "1" //false

此运算符 ("===") 用于执行自动类型转换的语言,例如。 php、Javascript。"===" 运算符有助于防止自动类型转换导致的意外比较。

【讨论】:

for '==' dataType 不重要 @mrmr68 Abstract Equality Comparison 的操作数类型非常重要 — 它用于将操作数强制转换为其他类型,以便进行比较。【参考方案6】:

严格相等运算符 (===) 的行为与抽象相等运算符 (==) 相同,只是不进行类型转换,并且类型必须相同才能被视为相等。

参考:Javascript Tutorial: Comparison Operators

== 运算符将在进行任何必要的类型转换后比较是否相等=== 运算符将进行转换,因此如果两个值的类型不同,=== 将简单地返回 false。两者都一样快。

引用道格拉斯·克罗克福德的优秀JavaScript: The Good Parts,

JavaScript 有两组相等运算符:===!==,以及它们的邪恶双胞胎 ==!=。好的工作按您期望的方式工作。如果两个操作数类型相同且值相同,则=== 产生true!== 产生false。当操作数属于同一类型时,邪恶双胞胎会做正确的事情,但如果它们属于不同类型,它们会尝试强制值。他们这样做的规则既复杂又难以忘怀。以下是一些有趣的案例:

'' == '0'           // false
0 == ''             // true
0 == '0'            // true

false == 'false'    // false
false == '0'        // true

false == undefined  // false
false == null       // false
null == undefined   // true

' \t\r\n ' == 0     // true

缺乏传递性令人担忧。我的建议是永远不要使用邪恶的双胞胎。相反,请始终使用===!==。刚才显示的所有比较都使用=== 运算符生成false


更新:

@Casebash 在 cmets 和 @Phillipe Laybaert's answer 中提出了一个关于对象的好观点。对于对象,===== 彼此一致(特殊情况除外)。

var a = [1,2,3];
var b = [1,2,3];

var c =  x: 1, y: 2 ;
var d =  x: 1, y: 2 ;

var e = "text";
var f = "te" + "xt";

a == b            // false
a === b           // false

c == d            // false
c === d           // false

e == f            // true
e === f           // true

特殊情况是当您将一个原语与一个评估为相同原语的对象进行比较时,由于其toStringvalueOf 方法。例如,考虑将字符串原语与使用String 构造函数创建的字符串对象进行比较。

"abc" == new String("abc")    // true
"abc" === new String("abc")   // false

这里== 运算符检查两个对象的值并返回true,但=== 发现它们不是同一类型并返回false。哪一个是正确的?这实际上取决于您要比较的内容。我的建议是完全绕过这个问题,只是不要使用 String 构造函数从字符串文字创建字符串对象。

参考http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3

【讨论】:

我还要指出 0 === -0 和 NaN !== NaN,这有时会让人感到困惑。如果要区分 ±0 并认为 NaN 相等,请使用 Object.is (ES2015) 软打字是一个功能。显然 Crockford 指出了设计决策的一些“人工制品”,但软打字仍然是一个特性。如果使用得当,绝对没问题。不要把婴儿和洗澡水一起扔掉。 你为什么需要使用-0 我有很多工作【参考方案7】:

我的推理过程使用 emacs org-mode 和 node.js 运行测试。

| use ==     | '' | '0' | false | 'false' | undefined | null | ' \t\r\n ' |
| ''         | x  | f   | t     | f       | f         | f    | f          |
| '0'        |    | x   | t     | f       | f         | f    | f          |
| false      |    |     | x     | f       | f         | f    | t          |
| 'false'    |    |     |       | x       | f         | f    | f          |
| undefined  |    |     |       |         | x         | t    | f          |
| null       |    |     |       |         |           | x    | f          |
| ' \t\r\n ' |    |     |       |         |           |      | x          | 



| use ===    | '' | '0' | false | 'false' | undefined | null | ' \t\r\n ' |
| ''         | x  | f   | f     | f       | f         | f    | f          |
| '0'        |    | x   | f     | f       | f         | f    | f          |
| false      |    |     | x     | f       | f         | f    | f          |
| 'false'    |    |     |       | x       | f         | f    | f          |
| undefined  |    |     |       |         | x         | f    | f          |
| null       |    |     |       |         |           | x    | f          |
| ' \t\r\n ' |    |     |       |         |           |      | x          |

我的测试脚本如下:运行> node xxx.js

var rowItems = ['', '0', false, 'false', undefined, null, ' \t\r\n ']
var colItems = rowItems

for(var i = 0; i < rowItems.length; i++) 
    for (var j = 0; j < colItems.length; j++) 
        var r = (rowItems[i] === colItems[j]) ? true : false;
        console.log(rowItems[i] + " = " + colItems[j] + " " + r + " [" + i + "] ==> [" + j + "]")
    ;

【讨论】:

【参考方案8】:

=== 检查相同边在 typevalue 中是否相等。


示例:

'1' === 1 // will return "false" because `string` is not a `number`

常见示例:

0 == ''  // will be "true", but it's very common to want this check to be "false"

另一个常见的例子:

null == undefined // returns "true", but in most cases a distinction is necessary

很多时候,无类型检查会很方便,因为您不在乎值是undefinednull0 还是""

【讨论】:

【参考方案9】:

使用== 运算符(平等

true == 1; //true, because 'true' is converted to 1 and then compared
"2" == 2;  //true, because "2" is converted to 2 and then compared

使用=== 运算符(身份

true === 1; //false
"2" === 2;  //false

这是因为等式运算符== 确实类型强制,这意味着解释器会在比较之前隐式尝试转换值。

另一方面,身份运算符=== 不进行类型强制,因此在比较时不会转换值,因此速度更快(根据This JS benchmark 测试)因为它跳过了一步。

【讨论】:

【参考方案10】:

为什么== 如此难以预测?

将空字符串 "" 与数字零 0 进行比较会得到什么?

true

是的,根据== 是正确的,一个空字符串和数字零是相同的时间。

不止于此,还有一个:

'0' == false // true

数组会变得很奇怪。

[1] == true // true
[] == false // true
[[]] == false // true
[0] == false // true

然后用字符串更奇怪

[1,2,3] == '1,2,3' // true - REALLY?!
'\r\n\t' == 0 // true - Come on!

情况变得更糟:

什么时候等于不等于?

let A = ''  // empty string
let B = 0   // zero
let C = '0' // zero string

A == B // true - ok... 
B == C // true - so far so good...
A == C // **FALSE** - Plot twist!

让我再说一遍:

(A == B) && (B == C) // true
(A == C) // **FALSE**

而这正是你使用原语得到的疯狂东西。

当您将 == 与对象一起使用时,这是一个全新的疯狂水平。

此时您可能想知道...

为什么会这样?

这是因为与“三等号”(===) 不同,它只检查两个值是否相同。

== 做了很多一大堆其他事情

它对函数有特殊处理,对空值、未定义、字符串有特殊处理,你可以命名它。

它变得很古怪。

事实上,如果你尝试编写一个函数来完成== 所做的事情,它会看起来像这样:

function isEqual(x, y)  // if `==` were a function
    if(typeof y === typeof x) return y === x;
    // treat null and undefined the same
    var xIsNothing = (y === undefined) || (y === null);
    var yIsNothing = (x === undefined) || (x === null);

    if(xIsNothing || yIsNothing) return (xIsNothing && yIsNothing);

    if(typeof y === "function" || typeof x === "function") 
        // if either value is a string 
        // convert the function into a string and compare
        if(typeof x === "string") 
            return x === y.toString();
         else if(typeof y === "string") 
            return x.toString() === y;
         
        return false;
    

    if(typeof x === "object") x = toPrimitive(x);
    if(typeof y === "object") y = toPrimitive(y);
    if(typeof y === typeof x) return y === x;

    // convert x and y into numbers if they are not already use the "+" trick
    if(typeof x !== "number") x = +x;
    if(typeof y !== "number") y = +y;
    // actually the real `==` is even more complicated than this, especially in ES6
    return x === y;


function toPrimitive(obj) 
    var value = obj.valueOf();
    if(obj !== value) return value;
    return obj.toString();

那么这是什么意思?

表示==很复杂。

因为它很复杂,所以当你使用它时很难知道会发生什么。

这意味着您最终可能会遇到错误。

所以这个故事的寓意是……

让你的生活不那么复杂。

使用=== 代替==

结局。

【讨论】:

【参考方案11】:

使用===如果你想在JavaScript中比较几个东西,它被称为严格相等,这意味着如果只有类型和值都相同,这将返回true strong>,因此不会对您进行任何不需要的类型更正,如果您使用==,您基本上不关心类型,并且在许多情况下您可能会面临松散相等比较的问题。

使用 ===

的严格相等

严格相等比较两个值是否相等。两个值都不是 在比较之前隐式转换为其他值。如果 值有不同的类型,这些值被认为是不相等的。 否则,如果值具有相同的类型并且不是数字, 如果它们具有相同的值,则它们被认为是相等的。最后,如果两者 值是数字,如果它们都不是 NaN,则它们被认为是相等的 和 是相同的值,或者如果一个是 +0 而一个是 -0。

var num = 0;
var obj = new String('0');
var str = '0';

console.log(num === num); // true
console.log(obj === obj); // true
console.log(str === str); // true

console.log(num === obj); // false
console.log(num === str); // false
console.log(obj === str); // false
console.log(null === undefined); // false
console.log(obj === null); // false
console.log(obj === undefined); // false

使用 ==

的松散相等

松散相等比较两个值是否相等,转换后 值到一个共同的类型。转换后(一方或双方可 进行转换),执行最终的相等比较 就像 === 执行它一样。松散相等是对称的:A == B 对于 A 和 B 的任何值,始终具有与 B == A 相同的语义 (应用转换的顺序除外)。

var num = 0;
var obj = new String('0');
var str = '0';

console.log(num == num); // true
console.log(obj == obj); // true
console.log(str == str); // true

console.log(num == obj); // true
console.log(num == str); // true
console.log(obj == str); // true
console.log(null == undefined); // true

// both false, except in rare cases
console.log(obj == null);
console.log(obj == undefined);

【讨论】:

我确实认为关于您应该/不应该做什么是主观的,并且会误导告诉某人始终使用特定操作。虽然我同意在大多数情况下我们关心使用 '===' 与 '==',但可能存在您希望完成类型转换的特殊情况。 - 想不出一个确切的用例,但也许设计是有一个松散的检查。无论如何,如果语言中包含某些内容,那是有原因的。在我看来,我们应该尽量避免笼统地说“总是做 x”。 我同意你的看法,如果你阅读了我的全部答案,你会看到我稍后会更详细地解释,老实说,我们使用的案例并不多,需要在 Javascript 中进行松散的比较.. . 我可以说不到 5%,甚至更少,但我对那些没有 js 背景的人使用“always”,他们认为 == 检查 JavaScript 中的严格比较,他们学会了谨慎而不是一开始就使用它,但随着他们变得更加专家,他们知道在哪些罕见的情况下他们可能会使用它。这就是为什么我这样写我的答案。【参考方案12】:

“我应该在 JavaScript 比较中使用== 还是===”的困境等于或类似于以下问题:“我应该使用'勺子'还是'叉子'来吃饭。

这个问题唯一合理的答案是

    您应该使用 Dynamic Type 比较,例如:== 进行 loose Type 比较。 您应该使用 Static Type 比较,例如:=== 进行 strong Type 比较。

那是因为它们不一样。它们的用途不同,也不打算用于相同的目的。

当然,“叉子”和“勺子”都是用来“吃”的,但您可以根据自己的食物选择使用它们。

含义:您将决定使用“勺子”,即:== 用于“汤”,和/或“叉子”,即:=== 用于采摘。

询问“吃”是使用“叉子”还是“勺子”更好 - 等于询问使用静态 [===] 与动态 [==] 等式是否更好,同上。在 JS 中。这两个问题同样是错误的,并且反映了对所讨论主题的非常狭隘或肤浅的理解。

【讨论】:

p.s.:JSLint (或 Crockford )坚持或要求您在处理相同类型的值时使用严格的类型比较是错误的。 JavaScript length 属性的类型始终为:数字。因此没有假阳性的空间或可能性。此外,当您可以使用!dSele_UNVEHtype.value.length 的直接简写代替时,就不需要dSele_UNVEHtype.value.length === 0 你为什么要回答一个已有 9 年历史的问题,它已经有 49 个答案,也有超过 5k 赞成票的公认答案,答案包含一个奇怪的类比,没有解释什么还没说完? 因为无论年龄多大,JavaScript 都有很多专业的误用。例如,您无法理解它的全部内容,也无法捕捉 Live Script 与静态类型语言相比差异的本质。以及为什么我们需要它的智能动力。 JavaScript 是为有创造力的聪明人而不是笨蛋而设计的。 是的,我同意 JavaScript 有很多误用。但是我仍然认为您的类比很奇怪,因为它很容易被误解,并且没有以有意义的方式涵盖核心基础知识。 给出的类比是有史以来最好的说明它们的区别和用例的质量。即使您是 JS 的完全新手,这也是学习绝对本质的最佳短文。并且同样好,可能比我最近关于如何清空 JS 数组 [真正] 的答案更好。【参考方案13】:

JavaScript 既有严格的比较,也有类型转换的比较。严格比较(例如,===)仅在操作数属于同一类型时才成立。更常用的抽象比较(例如==)在进行比较之前将操作数转换为相同的类型。

相等 (==) 运算符在操作数不属于同一类型时转换它们,然后应用严格比较。如果任一操作数是数字或布尔值,则尽可能将操作数转换为数字;否则,如果任一操作数是字符串,则尽可能将字符串操作数转换为数字。如果两个操作数都是对象,那么当操作数引用内存中的同一个对象时,JavaScript 会比较相等的内部引用。

语法:

x == y

例子:

3 == 3     // true
"3" == 3   // true
3 == '3'   // true

如果操作数严格相等(见上文)且没有类型转换,则身份/严格相等 (===) 运算符返回 true。

语法:

x === y

例子:

3 === 3 // true

供参考:Comparison operators(Mozilla 开发者网络)

【讨论】:

【参考方案14】:

JSLint 有时会给你不切实际的理由来修改东西。如果类型已经相同,=== 的性能与== 完全相同。

只有在类型不同的情况下才会更快,这种情况下不会尝试转换类型而是直接返回false。

所以,恕我直言, JSLint 可能用于编写新代码,但应不惜一切代价避免无用的过度优化。

意思是,当您知道 a 只能是字符串这一事实时,没有理由在像 if (a == 'test') 这样的检查中将 == 更改为 ===

以这种方式修改大量代码会浪费开发人员和审阅者的时间,而且一无所获。

【讨论】:

有趣的是,a.length===4 在 Firefox 中实际上比a.length==4。无论如何,这无论如何都是一种微优化,但这与人们声称的相反。【参考方案15】:

=== 运算符检查变量的值和类型是否相等。

== 运算符只是检查变量的值是否相等。

【讨论】:

【参考方案16】:

严格相等在很大程度上更好

Javascript 是一种松散类型的语言这一事实​​需要在您使用它时经常出现在您的脑海中。只要数据结构相同,就没有理由不使用严格相等,通过常规相等,您通常会自动进行值的隐式转换,这会对您的代码产生深远的影响。这种转换很容易出现问题,因为它们是自动发生的。

在严格相等的情况下,不会自动进行隐式转换,因为值必须已经是正确的数据结构。

【讨论】:

【参考方案17】:

建议将== 替换为=== 的原因是=== 运算符比== 更可靠。在我们的上下文中,可靠意味着=== 也用于类型检查。考虑到最佳编程实践,我们应该始终选择更可靠的功能而不是不太可靠的功能。同样,每当我们在大多数情况下考虑完全等于运算符时,默认情况下我们认为类型应该是相同的。正如=== 提供的一样,我们应该努力。

【讨论】:

【参考方案18】:

这意味着没有类型强制的平等 类型强制意味着 JavaScript 不会自动将任何其他数据类型转换为字符串数据类型

0==false   // true,although they are different types

0===false  // false,as they are different types

2=='2'    //true,different types,one is string and another is integer but 
            javaScript convert 2 to string by using == operator 

2==='2'  //false because by using === operator ,javaScript do not convert 
           integer to string 

2===2   //true because both have same value and same types 

【讨论】:

【参考方案19】:

== == = = 之间的区别

= 运算符用于仅分配 value= = 运算符用于仅比较 values 而不是 datatype = = = 运算符用于比较 valuesdatatype

【讨论】:

【参考方案20】:

首先,关于 Javascript 字符串 equals 的一些术语:双等号正式称为抽象相等比较运算符,而三等号称为严格相等比较运算符。它们之间的区别可以总结如下:抽象相等会在进行比较之前尝试通过类型强制来解析数据类型。如果类型不同,严格相等将返回 false。考虑以下示例:

console.log(3 == "3"); // true
console.log(3 === "3"); // false.
console.log(3 == "3"); // true
console.log(3 === "3"); // false.

使用两个等号返回真,因为字符串“3”在进行比较之前被转换为数字 3。三个等号看出类型不同,返回false。这是另一个:

console.log(true == '1'); // true
console.log(true === '1'); // false
console.log(true == '1'); // true
console.log(true === '1'); // false

同样,抽象相等比较执行类型转换。在这种情况下,布尔值 true 和字符串“1”都转换为数字 1,结果为 true。严格相等返回 false。

如果您了解自己已经很好地区分 == 和 ===。但是,在某些情况下,这些运算符的行为是不直观的。让我们再看一些例子:

console.log(undefined == null); // true
console.log(undefined === null); // false. Undefined and null are distinct types and are not interchangeable.
console.log(undefined == null); // true     
console.log(undefined === null); // false. Undefined and null are distinct types and are not interchangeable.

console.log(true == 'true'); // false. A string will not be converted to a boolean and vice versa.
console.log(true === 'true'); // false
console.log(true == 'true'); // false. A string will not be converted to a boolean and vice versa.
console.log(true === 'true'); // false

下面的例子很有趣,因为它说明了字符串文字与字符串对象不同。

console.log("This is a string." == new String("This is a string.")); // true
console.log("This is a string." === new String("This is a string.")); // false
console.log("This is a string." == new String("This is a string.")); // true
console.log("This is a string." === new String("This is a string.")); // false

【讨论】:

【参考方案21】:
var a = new String("123");
var b = "123";

alert(a === b); // returns false !! (but they are equal and of the same type)

在其中一个答案中看到了这一点。 ab 在这种情况下并不是真正的同一类型,如果您要检查 typeof(a) 你会得到 'object'typeof(b)'string'

【讨论】:

【参考方案22】:

Javascript 的类型很松散,就像 php 一样,

var x = "20";
var y =20;

if (x===y) // false

这总是会给你一个错误,因为即使变量的值相同,数据类型也不同

一个是字符串,另一个是整数

If(x==y)//true

然而,这只是检查内容是否相同,而不管数据类型如何......

我不想说值相等,因为字符串值在逻辑上不能等于 int 值

【讨论】:

【参考方案23】:

始终使用“===”,您将避免成千上万的错误。如今,不同的风格指南更倾向于使用 triple 相等,因为它比较考虑了操作数的类型。

【讨论】:

【参考方案24】:

一个未提及的使用=== 的原因 - 是在您与coffee-script 共存/交叉编译的情况下。来自Little Book on CoffeeScript...

JavaScript 中的弱相等比较有一些令人困惑的行为,并且通常是令人困惑的错误的根源。

解决方案是改用严格相等运算符,它由三个等号组成:===。它的工作方式与普通的相等运算符完全相同,但没有任何类型强制。建议始终使用严格相等运算符,并在需要时显式转换类型。

如果您经常与coffee-script 相互转换,您应该只使用===。事实上,coffee-script 编译器会强迫你...

CoffeeScript 通过简单地将所有弱比较替换为严格比较来解决这个问题,换句话说,将所有 == 比较器转换为 ===。您不能在 CoffeeScript 中进行弱相等比较,如果需要,您应该在比较之前显式转换类型。

【讨论】:

【参考方案25】:

是的,相等 == 和标识 === 运算符之间存在很大差异。 通常身份运算符执行得更快,因为没有进行类型转换。但如果这些值属于同一类型,您将看不到任何差异。 查看我的帖子The legend of JavaScript equality operator,里面解释了很多细节,包括类型转换和比较算法,还有很多例子。

【讨论】:

【参考方案26】:

JavaScript === vs ==.

0==false   // true
0===false  // false, because they are of a different type
1=="1"     // true, auto type coercion
1==="1"    // false, because they are of a different type

【讨论】:

【参考方案27】:

来自core javascript reference

=== 如果操作数严格相等,则返回true(见上文) 没有类型转换。

【讨论】:

【参考方案28】:

让我补充一下这个忠告:

如有疑问,请阅读specification!

ECMA-262 是一种脚本语言规范,JavaScript 是其方言。当然,在实践中,最重要的浏览器的行为方式比对应该如何处理某事的深奥定义更重要。但是了解为什么 new String("a") !== "a" 会很有帮助。

请让我解释一下如何阅读规范以澄清这个问题。我看到在这个非常古老的话题中,没有人对非常奇怪的效果有答案。因此,如果您可以阅读规范,这将对您的职业有极大的帮助。这是一种后天习得的技能。那么,让我们继续吧。

在 PDF 文件中搜索 === 会将我带到规范的第 56 页:11.9.4。严格等号运算符 ( === ),在涉足规范之后,我发现:

11.9.6 严格等式比较算法 比较 x === y,其中 x 和 y 是值,产生 truefalse。如下进行这样的比较: 1. 如果 Type(x) 与 Type(y) 不同,则返回 false。 2.如果Type(x)是Undefined,返回true。 3. 如果 Type(x) 为 Null,则返回 true。 4. 如果 Type(x) 不是 Number,请转到第 11 步。 5.如果x是NaN,返回false。 6.如果y是NaN,返回false。 7.如果x和y的数值相同,返回true。 8. 如果 x 为 +0 且 y 为 -0,则返回 true。 9. 如果 x 为 -0 且 y 为 +0,则返回 true。 10. 返回 false。 11.如果Type(x)是String,那么如果x和y是完全相同的字符序列(长度相同,对应位置的字符相同),则返回true;否则,返回 false。 12.如果Type(x)是Boolean,如果x和y都是true或者都是false,则返回true;否则,返回 false。 13. 如果 x 和 y 指代同一个对象或如果它们指代彼此连接的对象,则返回 true(参见 13.1.2)。否则,返回 false

有趣的是第 11 步。是的,字符串被视为值类型。但这并不能解释为什么 new String("a") !== "a"。我们是否有不符合 ECMA-262 的浏览器?

没那么快!

让我们检查操作数的类型。将它们包装在 typeof() 中,自己尝试一下。我发现new String("a")是一个对象,使用第1步:如果类型不同则返回false

如果您想知道为什么 new String("a") 不返回字符串,那么来做一些阅读规范的练习怎么样?玩得开心!


Aidiakapi 在下面的评论中写道:

来自规范

11.2.2 新运营商

如果 Type(constructor) 不是 Object,则抛出 TypeError 异常。

换句话说,如果 String 不是 Object 类型,它就不能与 new 运算符一起使用。

new 总是返回一个 Object,即使对于 String 构造函数也是如此。唉!字符串的值语义(参见步骤 11)丢失。

这最终意味着:new String("a") !== "a"

【讨论】:

【参考方案29】:

严格相等/比较'==='的Javascript执行流程图

非严格相等/比较'=='的Javascript执行流程图

【讨论】:

【参考方案30】:

javascript 是一种弱类型语言,即没有 C、c++ 中的任何数据类型,例如。 int、boolean、float 等,因此一个变量可以保存任何类型的值,这就是为什么这些特殊的比较运算符在那里

例如

var i = 20;var j = "20";

如果我们应用比较运算符,这些变量的结果将是

i==j //result is true

j != i//result is false

为此,我们需要一个特殊的比较运算符来检查变量的值以及数据类型

如果我们这样做

i===j //result is false

【讨论】:

以上是关于在 JavaScript 比较中应该使用哪个等号运算符(== vs ===)?的主要内容,如果未能解决你的问题,请参考以下文章

在 JavaScript 比较中应该使用哪个等号运算符(== vs ===)?

在 JavaScript 比较中应该使用哪个等号运算符(== vs ===)?

在 JavaScript 比较中应该使用哪个等号运算符(== vs ===)?

在 JavaScript 比较中应该使用哪个等号运算符(== vs ===)?

我可以使用三等号进行 JavaScript 字符串比较吗?

javascript基础:等号比较