还在纠结==和===是true还是false吗?看完遍打通了奇迹八脉任何比较都会了
还在纠结==和===是true还是false吗?看完遍打通了奇迹八脉任何比较都会了
一、原理
介绍之前先总结下:javascript中变量的类型有五种基本类型Undefined, Null, Boolean, Number和String;和其他对象类型Array, Function, Date等等。
==:等于,两者内容的比较,有两种情况:1.两者type类型不一样,会存在隐式转换;2.两者type类型一样,直接比较内容
隐式转换时遵循如下原则:
1.两者都是基本类型时,有一个是布尔类型时,优先调用Number()
将布尔类型转化为0/1;
2.两者都是基本类型时,一个是字符串一个是数字类型时,优先调用Number()
将字符串转化为数字;
3.基本类型和引用类型比较时,优先调用对象的valueOf()
转化为基本类型,如果返回不是基本类型再调用toString()
方法,转为字符串类型,再作比较;
4.引用类型和引用类型比较时,比较的是两者的引用的地址,不是同一个引用都不相同。
5.特例,null == undefined
,null,undefined和其他做比较都为false
===:三等于,严格等于,先比较两者的类型,再比较两者内容。
二、区别
总结:不相同的作比较时需要Number()的变量有Boolean
, Number
和String
三种类型,需要valueOf()和toString()有Object,Array,Function,Date等。
//Nmuber()
Number(true) // 1
Number(false) // 0
Number(1) // 1
Number("1") // 1
//valueOf
({a:'1'}).valueOf() // {a: "1"}
[1,2,3].valueOf() // [1, 2, 3]
(function test(){}).valueOf() // ƒ test(){}
(new Date('2020-05-26')).valueOf() // 1590451200000
// toString
({a:'1'}).toString() // "[object Object]"
[1,2,3].toString() // "1,2,3"
(function test(){}).toString() // "function test(){}"
(new Date('2020-05-26')).toString() // "Tue May 26 2020 08:00:00 GMT+0800 (中国标准时间)"
有引用类型比较时除了Date类型,其余都用toString转化为字符串类型,记住[]的toString为'';{} toSting为"[object Object]"
三、实例
1.简单类型比较
1 == true //true // Number Boolean
2 == true //false
1 == "1" //true // Number String
[] == "" //true // Object String
[] == false // true // Object Boolean
[] == 0 //true // Object Number
({}) == "[object Object]" // true
[] == {} //false
[] == [] //false
{} == {} //false
null == undefined //true
2.复杂类型比较
当引用类型重写了valueOf()和toString()时需也别注意,当toString返回的不是基本类型时并且和基本类型比较时会产生异常,和对象比较则不会
1)只重写valueOf()
不会报错,因为若返回引用类型则继续调原型链上的Object.prototype.toString()方法
var a = 1;
var obj = {valueOf: function(){ return {} }}
a == obj // false
2)重写valueOf()及toString()返回引用类型
和非引用类型比较时,会报错,因为toString()为比较做隐式转换的最后一道工序
var a = 1;
var obj = {valueOf: function(){ return {} }, toString: function(){ return {}}}
obj == a // Uncaught TypeError: Cannot convert object to primitive valueat <anonymous>:3:5
和引用类型比较时,不会报错,因为valueOf()和toString()都没有调用直接比较的引用地址
var a = 1;
var obj = {valueOf: function(){ return {} }, toString: function(){ return {}}}
obj == {} // false
3.if应用场景
if可以看做与布尔值true的比较
if(true) console.log("true"); //true
if(false) console.log("true");
if(1) console.log("true"); //true
if(0) console.log("true");
if(-1) console.log("true"); //true
if("true") console.log("true"); //true
if("1") console.log("true"); //true
if("0") console.log("true"); //true
if("") console.log("true");
if(null) console.log("true");
if(undefined) console.log("true");
if("null") console.log("true"); //true
if("undefined") console.log("true"); //true
if([]) console.log("true"); //true
if({}) console.log("true"); //true
if([0]) console.log("true"); //true
if(NaN) console.log("true");
4.误区
误区:
0 == "0" //true
0 == [] //true
"0" == [] // false
[] == '' // true
'0' == '' //false
"0" == [] 为 false
[].toString()后为字符串空,==不具备传递性,===才具备
参考文章:
https://dorey.github.io/JavaScript-Equality-Table/#three-equals