全等与相等是两种类型的相等操作符;他们的区别我们可以用两句话来说明:
全等与不全等的逻辑比较简单,我们主要来关注相等与不相等。当我们对两个操作数用 == 进行比较的时候,我们分两种情况:== 两边操作数的类型相同与不相同。我们都知道类型不相同时需要先转换类型,但是其中的转换规则是什么样的呢?也许许多人都不曾仔细研究过,下面我们来看一段代码: if (![] == []) { //Code }![] == [],true or false? 今天我们就通过分析![] == []来深入研究一下 == 的比较机制。 两边类型相同
当两边的类型相同时,比较的逻辑就跟 === 一样: console.log(5 == 5); //true console.log('abc' == 'abc'); //true console.log([] == []); //false,两个不同的引用地址 var a = [], b = a; console.log(a == b); //true 也许有人会说,既然[] == []为false,那么前面那个![] == []的结果就是true咯?!没错,但是其中的判断逻辑不是这么简单的,因为![]等于false,所以这个比较就相当于false == [],这时两边的类型不一样的,一个是Boolean,一个是Array,所以我们不能简单通过[] == []为false来判断![] == []为true,当我们将[]换成{},这时结果就不一样了。 console.log([] == []); //false console.log(![] == []); //true console.log({} == {}); //false console.log(!{} == {}); //false 也许你会感到糊涂,[]与{}同样是引用类型,为什么![] == []与!{} == {}的结果不一样呢?那是因为Array有其特殊的地方,这时后话,我们先来看下当 == 两边类型不相等时的转换规则。 两边类型不相同 当 == 两边操作数的类型不相同时,会将操作数的类型进行转换相同的类型,通常也叫强制转型,然后再比较其相等性,比如: console.log(5 == '5'); //true,将字符'5'转换成数字5再比较 console.log(false == 0); //true,先将布尔值false转换成数字0 在转换不同的数据类型时,相等和不相等操作符遵循下列基本规则:
另外有几个需要注意的地方:
根据以上规则,我们可以自己写一个比较相等的函数: function Equal(a, b) { var typeA = typeof a, typeB = typeof b; //如果有一个操作数是NaN,则总返回false //isNaN(undefined)返回true if ((isNaN(a) && typeA === 'number') || (isNaN(b) && typeB === 'number')) { return false; } //如果操作数类型相等,则比较它们的值,否则转换类型 if (typeA === typeB) { return a === b; } else { //将undefined转成null(实际上是不转的,此处只是方便后面的比较) if (typeA === 'undefined') { a = null; } if (typeB === 'undefined') { b = null; } if (a === null || b === null) { return a === b; } else if (typeA === 'object' || typeB === 'object') { //如果有一个是对象 //先调用其valueOf方法,如果返回还是object,则调用其toString方法 var o = (typeA === 'object' ? a : b).valueOf(), other = o === a ? b : a; if (typeof o === 'object') { o = o.toString(); } return Equal(o, other); } else { //如果有Boolean,将其转成Number if (typeA === 'boolean') { a = a ? 1 : 0; } if (typeB === 'boolean') { b = b ? 1 : 0; } //如果其中一个类型是Array,另外一个是Number,Number()返回number或NaN if (typeA === 'string' && typeB === 'number') { a = Number(a); } if (typeB === 'string' && typeA === 'number') { b = Number(b); } return Equal(a, b); } } } console.log(Equal([], [])); //false console.log(Equal(![], [])); //true console.log(Equal({}, {})); //false console.log(Equal(!{}, {})); //false console.log(Equal(NaN, NaN)); //false console.log(Equal(undefined, null)); //true console.log(Equal(false, null)); //false console.log(Equal(false, 0)); //true console.log(Equal(true, 2)); //false Array.toString() 那么为什么![] == []为true呢?其比较步骤如下:
因此: console.log(![] == []); //true console.log(0 == []); //true console.log(0 == ['']); //true console.log('0' == []); //false console.log('0' == [0]); //true console.log(true == [1]); //true 总结:由于相等和不相等操作符存在类型转换问题,而为了保持代码中数据类型的完整性,推荐使用全等和不全等操作符(已经强调很久了)。
文章来源 CODETC,欢迎分享,转载请注明地址:
http://www.codetc.com/article-293-1.html
|