javascript中的1===[1]如何

How is 1 == [1] in javascript?

本文关键字:如何 javascript 中的      更新时间:2023-09-26

最近我在一次采访中被问到这个问题。

 var a = 1;
 var b = [1];

a == b;将返回什么。

当我在chrome浏览器控制台上检查时,我得到了这个。

var a = 1;
var b = [1];
a == b;
true

我还检查了

var a = 1;
var b =(1);
a == b;
true

我知道b在大小为1的数组中。这是否意味着数组的大小被分配给了b。我真的很困惑。有人能给我解释一下其中的逻辑吗?

我并没有从Rayon的回答中真正理解valueOftoString在将对象转换为基元值时是如何发挥作用的;所以我深入研究了ECMAScript 2015规范。

警告:答案很长。

我们要检查表达式1 == [1]

12.10 Equality Operators开始,我们可以看到,在检索表达式值后,最后一步是

  1. 返回执行抽象相等比较的结果rval==lval

抽象相等比较在章节7.2.12抽象相等比较中定义。

7.2.12抽象平等比较
比较x==y,其中x和y是值,产生true或false。这样的比较如下:

  1. ReturnIfAbrupt(x)
  2. ReturnIfAbrupt(y)
  3. 如果类型(x)与类型(y)相同,则
    a.返回严格相等比较的结果x===y
  4. 如果x为null,y未定义,则返回true
  5. 如果x未定义,y为null,则返回true
  6. 如果Type(x)为Number,Type(y)为String,则返回比较结果x==ToNumber(y)
  7. 如果Type(x)为String,Type(y)为Number,则返回比较结果ToNumber(x)==y
  8. 如果Type(x)为Boolean,则返回比较结果ToNumber(x)==y
  9. 如果Type(y)为布尔值,则返回比较结果x==ToNumber(y)
  10. 如果Type(x)是String、Number或Symbol,而Type(y)是Object,则返回比较的结果x==ToPrimitive(y)
  11. 如果Type(x)是Object,Type(y)是String、Number或Symbol,则返回比较结果ToPrimitive(x)==y
  12. 返回false

表达式1 == [1]属于情况10
因此,基本上,正如预期的那样,数组[1]被转换为基元类型的值。

ToPrimitive7.1.1 ToPrimitive(input[,PreferredType])中定义

抽象操作ToPrimitive接受一个输入参数和一个可选参数PreferredType。这个抽象操作ToPrimitive将其输入参数转换为非Object类型。

我还没有包括完整的报价,因为唯一有趣的对于这个例子,部分是:

  1. PreferredType参数(实际上是hintvar)从"default"(因为它没有传递)转换为"number"
  2. 使用相同的参数调用OrdinaryToPrimitive

E现在是有趣的部分,OrdinaryToPrimitive执行以下操作:

  1. 断言:类型(O)为对象
  2. Assert:Type(hint)为String,其值为"String"或"number"
  3. 如果提示为"字符串",则
    a.让methodNames为«"toString","valueOf"»
  4. 否则,
    a.让methodNames为«"valueOf","toString"»
  5. 对于methodNames中的每个名称,按列表顺序执行
    a.让方法为Get(O,name)
    b.ReturnIfAbrupt(方法)
    c.如果IsCallable(方法)为true,则
    …i.设结果为Call(方法,O)
    …ii。ReturnIfAbrupt(结果)
    …iii.**如果Type(result)不是Object,则返回result。**
  6. 引发TypeError异常

因此,为了将[1]转换为基元值,运行时首先尝试调用valueOf。此方法返回数组本身,数组本身是一个对象,因此5.c.ii接下来调用方法toString
此方法以逗号分隔的列表形式返回数组的元素,因此它只返回字符串"1"

因此,我们简化比较1 == "1",根据抽象等式比较的规则,第6点,意味着将"1"转换为数字1,而不是执行平凡比较1 = 1

请持怀疑态度的读者查看严格平等比较在标准中的实际定义。


你可以玩这种转换来更好地理解它们,这里是一个示例游乐场HTML文件

<html>
    <head><title>title</title></head>
    <body>
        <script>
            var old_valueOf = Array.prototype.valueOf;
            var old_toString = Array.prototype.toString;
            Array.prototype.valueOf = function(){ console.log("Array::valueOf"); return old_valueOf.apply(this); };
            Array.prototype.toString = function(){ console.log("Array::toString"); return old_toString.apply(this); };
            console.log(1 == [1]); //Array::valueOf, Array::toString, true 
            Array.prototype.valueOf = function(){ console.log("Array::valueOf"); return 2; };
            console.log(1 == [1]); //Array::valueOf, false 
            Array.prototype.valueOf = function(){ console.log("Array::valueOf"); return {}; };
            Array.prototype.toString = function(){ console.log("Array::toString"); return {} };
            console.log(1 == [1]); //Array::valueOf, Array::toString, Uncaught TypeError: Cannot convert object to primitive value
        </script>
    </body>
</html>

如果将对象与数字或字符串进行比较,JavaScript会尝试返回该对象的默认值。运算符尝试使用对象的valueOftoString方法将对象转换为基元值,即StringNumber值。如果转换对象的尝试失败,则会生成运行时错误。【参考】

var a = 1;
var b = [1];
//What is happening when `(a==b)`
//typeof a;   ==> number
//typeof b;  ==>object
//Object is converted to Primitive using `valueOf` and `toString` methods of the objects
var val = b.valueOf().toString();
console.log('Values after conversion is: ' + val + '  And typeof converted value is:  ' + typeof val);
//typeof val; ==> string
//a == b; will be evaluated as `true` because `'1' == 1` hence..
console.log(a == b); //'1'==1 ==> true

由于转换的值是String类型,当比较numberstring时,string被转换为number值,然后应用严格的比较

这是由于进行比较的类型。

在javascript中,可以使用=====进行比较。在三重相等的情况下,这就是所谓的没有类型强制的相等,换句话说,这是一个严格的比较。

类型强制的平等

相反,这意味着使用双等于操作数是带有类型强制的等于

这意味着什么

简单地说,这意味着javascript将使用内置方法将值转换为基元类型,以便进行比较。具体地,这些方法是.valueOf().toString()

以下是一些例子:

0 == false   // true, auto type coercion
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

Ergo:

1 == [1] // true
1 === [1] // false, because they are of a different type