JavaScript中的相等运算符"==",你真的搞懂了么?

Brendan Eich在设计JavaScript的时候是没有加入类型系统的,所以JavaScript是一门动态语言,类型是进入执行上下文的时候可能才去确定,这就可能出现一个JavaScript变量在上一瞬间是String,下一瞬间就是Number了,在这个过程中,JavaScript变量进行了类型的转换。使用Javascript进行相等运算时,我们可能会用==,===和Object.is来进行比较两个值是否相等。

  1. 使用===时,恒等,严格比较运算符,不做类型转换,类型不同就是不等,NaN与NaN不相等。
  2. 使用Object.is()时,其行为与"==="基本一致,不过有两处不同:
  • +0不等于-0。
  • NaN等于自身。
  1. 使用时,不同类型的值也可以被看作相等。这可能会让很多的JavaScript困开发者感到困惑。使用""时,不同的数据类型都发生了哪些类型变化过程呢?

Javascript数据类型

在讲到类型转换之前,我们把JavaScript的数据类型再进行梳理一遍,最新的 ECMAScript标准定义了 8种原始数据类型,8种原始数据类型又分为7种基本数据类型和1种引用类型。

  • 基本类型
    Undefined、 Null、 String、 Number、 Boolean、Symbol和BigInt这7种数据类型都是属于基本类型,基本类型都是不可变的,不可变是指基本类型本身和一个赋值为基本类型的变量的区别。变量会被赋予一个新值,而原值不能像数组、对象以及函数那样被改变。
  • 引用类型:Object(对象),包括了数组(Array)、函数(Function)、正则(RegExp)和日期(Date)。

不同类型的值使用“==”运算符后的转换规则

类型(x) 类型(y) 类型(y)
null undefined true
undefined null true
数字 字符串 x == toNumber(y)
字符串 数字 y== toNumber(x)
布尔值 任何类型 toNumber(x) == y
任何类型 布尔值 x == toNumber(y)
字符串或数字 对象 x == toPrimitive(y)
对象 字符串或数字 toPrimitive(x)== y

toNumber对不同类型值的转换规则:

  • undefined: NaN
  • null: +0
  • Boolean:true:1,flase: 0
  • 数值返回对应的数值

toPrimitive对于基本类型不做转换,输出等于输入,对于对象,如果对象的valueOf方法的结果是原始值,则返回原始值,如果对象的toString方法返回的是原始值,则返回这个值,其他情况则返回一个错误。

toNumber和toPrimitive属于内部的方法ecma对于这两个方法的描述

例子:
1 console.log('juejin' ? true : false); // true
2 console.log('juejin' == true); // false

第一行的代码执行结果是true,第二行代码的执行结果是false,为什么会出现这样的结果呢?

  1. 按照上面给出的规则,true会被toNumber方法转换成1,即变成了'juejin' == 1,
  2. 'juejin'有被toNumber方法转换成NaN,即最后的表达式变成了NaN == 1,所以返回false。
    按照上面的方法,那'juejin' == false是不是会返回true呢?答案还是false,为什么呢?
  3. 按照上面给出的规则,false会被toNumber方法转换成0,即变成了'juejin' == 0,
  4. 'juejin'有被toNumber方法转换成NaN,即最后的表达式变成了NaN == 0,所以返回false。

扩展-数据类型判断

  1. typeof,基本数据类型,除了null之外,可以通过typeof操作符进行类型的判断:
  • undefined:typeof instance === "undefined"
  • Boolean:typeof instance === "boolean"
  • Number:typeof instance === "number"
  • String:typeof instance === "string
  • BigInt:typeof instance === "bigint"
  • Symbol :typeof instance === "symbol"
    null也是基本类型, typeof null === "object",这是JS语言本身的一个bug。不同的对象在底层都表示为二进制,在js中二进制前三位都为0的话会被判断为object类型,null的二进制表示全是0,自然前三位也是0,所以执行typeof时返回"object"。
    另外,引用类型里面的function也可以使用typeof判断:
  • Function :typeof instance === "function"
    其余的引用类型一律返回"object"。
  1. instanceof

instanceof运算符用来检测constructor.prototype是否存在于某个实例对象的原型链上。

function Class1() {
    console.log('Class1');
}

function Class2() {
    console.log('Class2');
}

const obj1 = new Class1();

obj1 instanceof Class1; // true

obj1 instanceof Class2; // false

Class1.prototype = {};

obj1 instanceof Class1; // false

除此之外,Object.prototype.toString.call和construct也可以进行数据类型的判断。

知识共享许可协议
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
comments powered by Disqus