当前位置: 首页 > 后端技术 > Node.js

Javascript隐式转换

时间:2023-04-03 18:16:29 Node.js

判断两个变量是否相等是编程中非常重要的操作。当谈到比较字符串、数字和布尔值是否相等时,问题就简单多了。但是当谈到比较对象时,事情就变得复杂了。ECMAScript中最早的相等和不等运算符在执行比较之前将对象转换为相似类型。后来,有人质疑这种转换是否合理。最后,ECMAScript的解决方案是提供两组运算符:相等和不等式——在比较之前转换,以及一致和不一致——比较而不转换。这里我们只对相等性做一些讨论。“==”相等时的隐式转换对于“==”运算符,通常在比较它们是否相等之前进行隐式转换(强制转换)。隐式转换规则:如果一个操作数是布尔值,则先转换为数值再比较是否相等——false转换为0,true转换为1;如果一个操作数是一个字符串,另一个操作数是一个值,在比较相等之前将字符串转换为值;字符串转值:(1)将数值类型的字符串转为相应的十进制值;(2)一个空字符串将被转换为0;(3)其余全部转为NaN;(NaN不等于任何值,包括它自己)如果一个操作数是对象而另一个不是,则调用该对象的valueOf()方法,将得到的Basic类型值按照前面的规则进行比较;下面通过一个简单的例子来看看JS的底层转换规则。//根据第三条隐式转换规则,调用了对象的valueOf方法[].valueOf()//[]//此时变为[]==false,又回到原来的情况。这个时候JS底层返回是怎么处理的呢?//实际上,如果调用valueOf得到的返回结果不是原来的值,JS底层会调用对象的toString方法将对象转为字符串。对于这个过程,我们可以通过下面的例子来验证。[].valueOf()//[][].toString()//''//以上是这两个方法的默认行为,在下面的例子中我们不改变默认行为[].__proto__.valueOf=()=>{console.log('valueOf');返回[];}[].__proto__.toString=()=>{console.log('toString');返回'??';}[]==false//运行的结果是valueOftoStringtrue//这验证了上面的解释   //我们也可以通过下面的方式从侧面验证JS底层的默认转换行为[].__proto__.valueOf=()=>{console.log('valueOf');返回'??';}[].__proto__.toString=()=>{console.log('toString');返回'??';}[]==false//valueOftrue[].__proto__.valueOf=()=>{console.log('valueOf');返回[];}[].__proto__.toString=()=>{console.log('toString');返回[];}[]==false//JS报UncaughtTypeError:Cannotconvertobjecttoprimitivevalue现在我们明白为什么示例中的空对象不等于false了吗?从正常的角度来看,数组就是对象,为什么空数组等于false,为什么空对象不等于false?//现在我们可以参考上面的隐式转换过程,对空对象手动执行这个过程,结果如下({}).valueOf()//{}({}).toString()//'[objectObject]'//此时我们发现了空对象和空数组的默认行为之间的区别。在toString方法中,由于数组会重写继承自对象的toString方法,通过','将数组中的每个元素链接成一个字符串//此时就变成了'[objectObject]'==false//根据第二条规则,得到最终结果false隐式转换的特殊规则:null和undefined相等。在比较相等之前,null和undefined不能比较undefined被转换为任何其他值。如果其中一个操作数是NaN,则相等运算符返回false,不等运算符返回true。如果两个操作数都是对象,则比较它们是否是同一个对象。(比较引用类型的地址是否相同)null==undefined//trueNaN==NaN//falseNaN!=NaN//truefalse==0//trueundefined==0//truenull==0//真