摘要:在比较字符串数值和布尔值的相等性时,问题还比较简单。后来,有人提出了这种转换到底是否合理的质疑。相等时的隐式转换对于操作符,通常都会先隐式转换强制转换,然后再比较它们的相等性。要比较相等性之前,不能将和转换成其他任何值。
确定两个变量是否相等是编程中的一个非常重要的操作。 在比较字符串、数值和布尔值的相等性时,问题还比较简单。但在涉及到对象的比较时,问题就变得复杂了。最早的 ECMAScript 中的相等和不等 操作符会在执行比较之前,先将对象转换成相似的类型。后来,有人提出了这种转换到底是否合理的质疑。 最后,ECMAScript 的解决方案就是提供两组操作符: 相等和不相等——先转换再比较,全等和不全等——仅比较而不转换。 此处我们只对相等做一些讨论。
"==" 相等 时的隐式转换
对于 "==" 操作符,通常都会先隐式转换(强制转换),然后再比较它们的相等性。隐式转换规则:
如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false 转换为 0,而true转换为 1;
如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值;
字符串转换为数值:
(1)数字类型的字符串,会被转成对应十进制的数值; (2)空字符串会转换成0; (3)其余的全都会转换为NaN;(NaN 与任何值都不相等,包括自身)
如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf()方法,用得到的基本类型值按照前面的规则进行比较;
下面可以通过一个简单的例子来看一下 JS 底层的转换规则。
// 根据隐式转换规则第三条 调用对象的 valueOf 方法 [].valueOf() // [] // 这时就变成 [] == false ,又回到原来的情况,这时JS底层又是怎么处理的呢? // 其实 JS 的底层在调用 valueOf 得到的返回结果如果不是原始值时,就会调用对象的 toString 方法将对象转换成字符串。对于这个过程我们可以通过一下的例子来验证。 [].valueOf() // [] [].toString() // "" //上面是 这两个方法的 默认行为,在下面的例子中我们不改变默认行为 [].__proto__.valueOf = () => { console.log("valueOf"); return []; } [].__proto__.toString = () => { console.log("toString"); return ""; } [] == false // 运行的结果为 valueOf toString true // 这样就验证了上述的说明 // 我们还可以通过下面的方式,从侧面在次验证 JS底层默认的转换行为 [].__proto__.valueOf = () => { console.log("valueOf"); return ""; } [].__proto__.toString = () => { console.log("toString"); return ""; } [] == false // valueOf true [].__proto__.valueOf = () => { console.log("valueOf"); return []; } [].__proto__.toString = () => { console.log("toString"); return []; } [] == false // JS 报错 Uncaught TypeError: Cannot convert object to primitive value
现在我们可以来看看例子中 空对象为什么不等于 false?从正常的角度来讲,数组就是一个对象,为什么空数组等于 false,而空对象为什么和 false 不相等?
//现在我们可以参照上面隐式转换的过程,对空对象手动的执行这个过程,结果如下 ({}).valueOf() // {} ({}).toString() // "[object Object]" // 这时我们发现 空对象 与 空数组默认行为的区别了,在 toString 方法上,由于数组会对继承自对象的 toString 方法进行重写,将数组中的每个元素通过 "," 链接成一个字符串 // 这时就变成了 "[object Object]" == false // 根据规则第二条,得到最后结果 false隐式转换的特殊规则:
null 和 undefined 是相等的。
要比较相等性之前,不能将 null 和 undefined 转换成其他任何值。
如果有一个操作数是 NaN,则相等操作符返回 false,而不相等操作符返回 true。
如果两个操作数都是对象,则比较它们是不是同一个对象。(比较引用类型的地址是否相同)
null == undefined // true NaN == NaN // false NaN != NaN // true false == 0 // true undefined == 0 // true null == 0 // true
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/100911.html
摘要:具体的行为取决于参数的类型。说到,就不得不提一下方法,方法自带隐式类型转换,该方法在测试其参数之前,会先调用方法将其转换为数字。全等运算符会先进行数据类型判断,并且不会发生隐式类型转换。 类型转换还不行?还非得隐式?这是什么高级玩意? 废话不多说,我们先上一盘?,额,不对,先看一个例子吧。 3 + true 实际上在大多数编程语言中,都会认为上面这个表达式是错误的。因为布尔表达式与算术...
摘要:强制类型转换作为程序员,你一定获取过当前系统的时间戳。比如对于变量而言,此次强制类型转换是隐式的。然而则是非常典型的显式强制类型转换。隐式强制类型转换大部分被诟病的强制类型转换都是隐式强制类型转换。 JavaScript 强制类型转换 作为 JavaScript 程序员,你一定获取过当前系统的时间戳。在 ES5 引入 Date.now() 静态方法之前,下面这段代码你一定不会陌生: v...
摘要:虽然你可能很惊讶甚至可能怀疑是的但是这都是有语言自己的一个隐式类型转换的套路。基本的隐式类型转换基本类型的隐式转换这个其实我们使用的最多例如结果返回的是而不是这就是类型的隐式转换。 基本上所有的语言都有 隐式类型转换 ,但是对于 弱类型语言(JS) 来说 ,隐式类型转换会比 强类型语言(Java) 带来更大的副作用,有些行为甚至是不可思议的。虽然你可能很惊讶 ,甚至可能怀疑是 JS 的...
摘要:所谓装箱转换,正是把基本类型转换为对应的对象,他是类型转换中一种相当重要的种类。拆箱转换在标准中,规定了函数,它是对象类型到基本类型的转换即,拆箱转换。拆箱转换会尝试调用和来获得拆箱后的基本类型。 JavaScript隐式类型转换 基本数据类型 ECMAScript 一共定义了七种 build-in types,其中六种为 Primitive Value,Null, Undefined...
摘要:显示的调用转换过程称为显式强制类型转换,隐式的情况称为隐式强制类型转换。隐式强制类型转换让代码变得晦涩难懂而又便捷而奇妙。事实上,允许在比较中进行强制类型转换,而不允许。如果有并且返回基本类型值,就使用该值进行强制类型转换。 JavaScript是一种非常灵活的现代编程语言,灵活到使用者极其容易被忽视的它那广阔的世界以及它带给我们的无限遐想空间。本文将对JavaScript最最基础也最...
摘要:看下面的代码和会对操作数执行条件判断,如果操作数不是布尔值,会先执行类型转换后再执行条件判断。大家记住这个规则布尔值如果与其他类型进行抽象比较,会先用将布尔值转换为数字再比较。 在上一篇中我们聊过了 JS 类型转换的规则和我发现的一些常见书籍中关于类型转换的一些小错误,当碰到显示类型转换的时候大家可以按照这些规则去拆解出答案。但 JS 中存在一些很隐晦的隐式类型转换,这一篇就来谈下我对...
阅读 1236·2021-09-22 15:18
阅读 2565·2021-09-22 15:17
阅读 2204·2019-08-30 15:55
阅读 1527·2019-08-30 15:54
阅读 1012·2019-08-30 13:12
阅读 597·2019-08-30 13:12
阅读 1652·2019-08-29 11:33
阅读 1413·2019-08-26 17:04