真正接触过JS
的读者都知道JS
是一个弱类型语言,当你进行比较或者运算的时候,它会悄悄地给你转换一些东西,来来来,我们先试试如下这几个,同时也会讲述他们的比较的顺序和原理
1.对象和原始值比较
都是转换为原始值比较
我们构造这样一个对象
var a = {
toString : function(){
console.log('toString');
}
};
a == false;
/*打印结果:
toString
false
*/
非常普通,这里我们可以发现当你比较一个对象和布尔类型的时候,他会悄悄运行toString
函数,然后再进行判断,我们将代码又改为如下形式:
var a = {
toString : function(){
console.log('toString');
},
valueOf : function(){
console.log('valueOf');
}
};
a == false;
/*打印结果:
valueOf
false
*/
加了一个valueOf
函数,让人惊喜的是,valueOf
被打印了出来,但是toString
没有被打印。
如此我们基本就可以知道了一个对象跟布尔类型进行比较的时候会进行的转换,就是检查是不是存在valueOf
函数,如果有就直接通过调用valueOf
处理,如果没有就检查是不是有toString
函数,如果有就调用toString
,那布尔类型又是怎么转换的呢,如果不说Boolean
对象的话,布尔类型一定是转换为数字,不管在什么条件下,布尔类型最终都是转换为数字,因为最开始是没有布尔类型的,布尔类型只是数字的特例而已。
然而这里需要注意的是Boolean
对象,Number
,String
这些封装了原始值的对象,他们会让你懵逼。
好了,这里我们就大大的提到一个概念
就是两个值比较必须是同一类型的,什么呢,即便是你写成不同类型的比较,javascript
处理也是尽可能将他们转换到相同的类型,如果转不了,是会报错的。
最简单的检验方法就是将上述的代码中的valueOf
和toString
去掉,运行一下这份代码,分分钟钟报错。
{}==1
因为无法都转换为数字,所以比较不了,就会报错。
所以呢,由于基本数据类型即原始值都已经内部处理好转换问题了,所以我们比较一个数字和字符串,或者是布尔,又或者是null
,undefined
也好,都不会报错,只是比较的结果是true
还是false
而已,而针对Boolean
这些对象,即便他们说的也是布尔类型啊,字符串类型啊,但是他们是封装原始值的对象,那么他们就会进行如下的规则转换比较,这个比较对所有的对象和原始值比较都适用,都一样。
如果是一个对象与原始值比较时,JavaScript
会尝试返回对象的默认值,接着尝试将对象转换为其原始值。也就是说对于对象,是先返回他们的本身,看类型是不是一样,然后才去返回他们转换的原始值。
String.prototype.toString = function(){console.log('-toString')};
String.prototype.valueOf = function(){console.log('-valueOf')};
var b = new String('1');
'1' == b;
//这里返回false的原因是因为我的toString和valueOf没有返回值而已,但是能比较了并且打印出了-valueOf表明进行了转换
字符串以及数字的情况和这个一样,null
和undefined
排除在外。
2原始值和原始值比较
当我们的数字和字符串进行比较的时候,JavaScript
尝试将数字字面量转换为数字类型的值。 首先, 一个数学上的值会从数字字面量中衍生出来,然后得到被四舍五入后的数字类型的值,而布尔类型和数字比较也是转换为数字,其中原始值null
和undefined
比较就有点尴尬了,先跳过。
3.对象和对象比较
直接是比较他们的引用
4.null
和undefined
的畸形
针对undefined
的比较,当我们用===
的时候,只有当一个变量没有被赋值时就会返回true
var x;
x===undefined
而当我们用==
号时,还会检查x
是不是null
,如果是会返回true
。
5.===
和==
使用时的注意事项
对于两个拥有相同字符顺序,相同长度,并且每个字符的位置都匹配的字符串,应该使用严格比较运算符。
对于两个数值相同的数字应该使用严格比较运算符,
NaN
和任何值不相等,包括其自身,正数零等于负数零。对于两个同为
true
或同为false
的布尔操作数,应使用严格比较运算符。不要使用严格比较运算符或比较运算符来比较两个不相等的对象。
当比较一个表达式和一个对象时,仅当两个操作数引用相同的对象(指针指向相同对象)。
对于
Null
和Undefined
类型而言,应使用严格比较运算符比较其自身,使用比较运算符进行互相比较。
6.知识提升
我们前面对于null
和undefined
的比较相对模糊,这里升华一下。
(null
是一个表示”无”的对象,转为数值时为0
;undefined
是一个表示”无”的原始值,转为数值时为NaN
。)这个性质只是在运算时才有作用,比较时不是这样的。
原因就是我们的null
和undefined
已经都是原始值了,即便null
是一个对象,但是也是当成一个原始值了,而原始值在比较会有区分,只有undefined
和null
会在比较时相互转换从而在==
运算符的结果中返回true
。
null
是对象,而undefined
则是一个原始数据类型,当我们typeof null
时就是"object"
而undefined
则就是"undefined"
。
这里又可以解释上面undefined
和null
,因为null
是一个对象,而它又是一个原始值,那么他的转换关系javascript
已经确定好了,个人无法知道它内部是怎么处理的,只知道null
在和undefined
比较的时候会转换为undefined
。
null
表示的是此处不应该有值,而undefined
则表示此处要有值,只是还没有赋值,这是两个表示的不同含义。