简单介绍一下 '==' ,毕竟这也是js中常见的坑,如果有问题欢迎大家指正,
[TOC]
相同类型的 '=='
总的来说,相同类型的 == 和 === 是一样的。
类型相同的基础类型
这个就很直接了,对于基础类型直接就是干,一样就相等,不一样就不等,Symbol和NaN是特例,Symbol是因为自己的特性,NaN,not a Number(翻译过来就是说这玩意不是数字,在数字上面表示的NaN就没啥意义)
var a = 1,b = 2;
console.log(a == b);
a = false,b = true;
console.log(a == b);
a = "123",b = "123";
console.log(a == b);
console.log(NaN == NaN) ;//false
类型相同的Object类型
//这个其实也是有点意思的,得从js变量说起,js的变量在我的理解下和c语言的引用是一样的。
//这个Object之间的 == 说实话也是和基础类型一样,只是不那么直观,看如下代码
var a = {}, b = {}
console.log(a == b)
b = a;
console.log(a == b)
//大概通俗易懂的就是,有明显的 b = a 或者 a = b 之后对象 的 == 才会是true
// 从引用层面来说,就是a 指向的地址和 b 指向的地址相同,其实基础变量也可以理解为这样判断的
相同类型的判断就大概如上,很直接
不同类型的 '==' 判断
这个就有点意思了,知乎上有个大神画了张图,感觉很厉害,这里就不搬下来了
null 和 undefined
这俩和其他类型比较都是false,但是互相比较就是true
console.log(undefined == null);//true
console.log(null == undefined);//true
基础类型的比较 Number,Boolean,String,都是转为Number 的
Boolean
Boolean 只能转 0 或者 1
所以Boolean 和其他值的比较大概就是,数字 0 和 1 和其他类型进行比较
console.log(false == 0);//true
console.log(false == '0');//true
console.log(false == '');//true
console.log(true == 1);//true
console.log(true == '1');//true
Number
Number 啥也不用干,就放在那里作为被比较的对象
强转规则参照
console.log(Infinity == 1/0);//true
console.log(-Infinity == -1/0);//true
console.log(false == 0);//true
console.log(true == 1);//true
console.log(1 == '1');//true
console.log(0 == '');//true
console.log(0 == []);//true
//NaN 是个有点意思的
console.log(NaN == NaN);//false
console.log(NaN == !NaN);//false
String
遇到Boolean和Number时 转Number ,其他也没啥了哈
强转规则参照
//Boolean
console.log(false == '0');//true
console.log(false == '');//true
console.log(true == '1');//true
console.log(false == 'false');//'false' 这个是烟雾弹,‘false’是有字符的,参照基础变量的强转,就转为NaN了
console.log(255 == '0xFF');//true
console.log(255 == '0255');//true
console.log(-Infinity == '-Infinity');//true
console.log(Infinity == 'Infinity');//true
Object 这个玩意非常有意思
就是一个转换,调用Primitive方法实现的,具体是调用Object的valueOf,如果valueOf返回的是对象,则调用toString,否则就直接用valueOf返回的值。
上面这段话要仔细品味呀,有点意思的
有些东西需要多实践的 ,敲敲代码运行代码感受下js设计者的心思
var a = {}
a.toString = function(){ return '2'};
a.valueOf = function(){return 1}
console.log(a == 1,a=='2');//true ,false
var c = {};
c.toString = function(){ return 'c'};
a.valueOf = function(){return c}
console.log(a == 'c');//false
console.log({} == '[object Object]')
取反操作,很骚
为什么取反操作就骚起来了呢,主要是对于取反操作来说,所有的其他类型都会转为Boolean类型,转换规则是null,undefined,0,-0,NaN,空字符串(“”)为false,其他全为true,所以取反操作就很容易做一些坑,比如![] , !+[]
补充一个小知识,Array.prototype.toString 返回的值很有意思的,有很多人那这个来玩,说白了就是利用js的各种强转和运算符优先级来搞事情,不是什么值得骄傲的事。
运算符优先级 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
var a = ['a',['b',['c'],'d'],'e']
console.log(a == 'a,b,c,d,e');//true
//暂时没看源码,但是大概可以理解为
//数组的toString 相当于每一项调用toString之后再 调用join(',')
//所以看下面的
console.log([] == 0);//true
console.log([[['0']]] == 0);//true
console.log([] == ![]);//true -- ![] 为bool值,转number 为 0 ,[] toString 为 ‘’ 转number 为 0
console.log([] == []);//false --同类型,都是Object,引用地址不一样
//这段代码的解析看下面
console.log((![] + [])[ -~!+[]+!+[] ]+({}+[])[-~!+[]] )
//解析一段小代码 ![] + [] -》 []为Object且不为空 ,所以![] 为false, false + [] ,不同类型,[] 调用toString() 即得false字符串,
// 按照运算符优先级,~ 和 !高于 +-,但是逻辑操作从右到左,即+[] 会作为左边第一个!的对象,+[]即把[]转为数字0, 即-~!(+[]) --> -~!(0) —-> -~(true) --> -~(1) --> -(-2) --> 2
//所以 2 + !+[] = 3 和上面一样 +[]为0 , +!0 = +1,
// 即得 (‘false’)[3] --> s
//同理 {} + [] 对象相加,调用其toString , 普通对象的tostring 返回的是 [object Object] ,数组的toString上面有说,所以这里返回的是“” 即得字符串 ‘[object Object]’
// -~!+[] 逻辑操作从右到左,优先级高于 +-*/ 所以我们优先看!+[] -> 1 取反得-2 再取相反数得 2
// 即得(‘[object Object]’)[2] ---> b
// 与上面的操作连接起来,这也就是那些所谓的js 装x来骂人的词了。
网友评论