基于面试题[] == ![] 引发的一系列问题

这个问题是不是一脸懵,往下看

在JavaScript中 == (“double equals”)被称为抽象相等比较("loose equality"),也叫做非严格相等。在比较两个值是否相等之前,两个被比较的值会转化为相同类型(等式两边都有可能被转化),转化完成之后再进性===的比较。

相等操作符的比较转化规律如下表:

B B B B B B
Undefined Null Number String Boolean Object
A Undefined true true false false false IsFalsy(B)
A Null true true false false false IsFalsy(B)
A Number false false A === B A === ToNumber(B) A=== ToNumber(B) A== ToPrimitive(B)
A String false false ToNumber(A) === B A === B ToNumber(A) === ToNumber(B) ToPrimitive(B) == A
A Boolean false false ToNumber(A) === B ToNumber(A) === ToNumber(B) A === B ToNumber(A) == ToPrimitive(B)
A Object false false ToPrimitive(A) == B ToPrimitive(A) == B ToPrimitive(A) == ToNumber(B) A === B

在上面表格中,ToNumber(A)表示尝试将A转化为数字,“ToPrimitive(A)”尝试调用A的“toString”和“valueOf“方法将参数 A 转换为原始值(Primitive)。

一般而言,根据 ECMAScript 规范,所有的对象都与 undefined 和 null 不相等。但是大部分浏览器允许非常窄的一类对象(即,所有页面中的 document.all 对象),在某些情况下,充当效仿 undefined 的角色。相等操作符就是在这样的一个背景下。因此,IsFalsy(A) 方法的值为 true,当且仅当 A 效仿 undefined。在其他所有情况下,一个对象都不会等于 undefined或 null。

上面是mdn关于==的描述

以下是总结
1、undefined 和 null 之间相等 与其余都不相等(对象里的document.all除外不过基本遇不到)
2、number 与 string 比较 string先转成number然后再做对比,
number与boolean比较也是如此
number与object比较object先调用ToPrimitive方法转成原始值再做比较
3、String 与 boolean值比较 两者都转化为number类型
String与object比较object先调用ToPrimitive方法转成原始值再做比较
4、boolean与object比较object先调用ToPrimitive方法转成原始值,boolean转化为number 然后比较

下面我们来一条一条的试试

//num,undefined与各个类型比较
var num = 1;
var str = 'sd';
var bol = true;
var obj = {a:1}
var arr = [1]

undefined == null //true
undefined == num //false
undefined == str //false
undefined ==  bol//false
undefined ==  obj //false

null == num //false
null == str //false
null ==  bol//false
null ==  obj //false

//number与各个类型比较
1 == 'ss' //false 先将‘ss’转化成number 也就是 Number('ss') 得到的是NaN,NaN与任何东西都不想等
0 == ‘’ //true 先将‘’转化为number也就是Number('') 得到 0 所以为true
1==true//true, 将true转化为number类型,Boolean,true为1false为0 显而易见为true
//ToPrimitive方法是先调用object的valueOf,如果可以返回原始数字那么就返回,如果不能,则调用toString方法
1 == obj //false obj的valueOf返回的是对象本身不是原始值所以继续调用obj的toString方法得到'[object Object]'然后就是 1 == '[object Object]' 为false
//如果重写了valueOf那么表现就不一样了
Object.prototype.valueOf = function(){
  return 1
}
1 == obj //true 因为这时候调用valueOf的时候返回了一个原始值,就不再调用toString方法

//string 与各个类型的比较
'sdf' == true//false 二者都要转化number类型,转化完以后 NaN === 1 为false
'sdf' == ['sdf'] //true 对象先调用valueOf方法返回的是数组本身非原始值,继续调用toString方法 得到字符串‘sdf’所以为true
true == obj // false 对象先调用valueOf方法返回的是数组本身非原始值,继续调用toString方法 得到字符 '[object Object]'  布尔值与字符串比较二者都转为number类型1===NaN 得到false


//Boolean值与各个类型比较
true == ['1'] // true 对象先调用valueOf方法返回的是数组本身非原始值,继续调用toString方法 得到字符 '1'  布尔值与字符串比较二者都转为number类型1===1 得到true

现在我们再来看这个题目

[] == ![] //首先右边有逻辑!这个优先级要高于== 先处理它 逻辑运算符!是将变量转变成boolean再取反
//那么第一步就是Boolean([]) 我们都知道Boolean 只有”“、0、-0、undefined、null、NaN、false这些返回false其余都是true,所以这里是true,取反得到false
[] == false
//上面我们知道了object与boolean比较,object调用valueOf,数组的valueOf是本身不是原始值,那么继续调用toString得到空字符串'',布尔值false转数字类型是0
'' == 0
//空字符串转数字类型得到0,所以
0 === 0 //true

好了,这次分享就到这里,想看具体的可移步MDN
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Equality_comparisons_and_sameness

你可能感兴趣的:(基于面试题[] == ![] 引发的一系列问题)