-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
彻底终结 Javascript 背后的隐式类型转换 #104
Comments
通哥厉害👍
|
感谢 @browsnet 指点! 1倒是知道, 不过面试用到的场景不多, 2确实是学习了 |
我最喜欢的是 {} > {}
{} == {}
{} >= {} |
@hjin-me 大王果然变态! |
@chunpu 所以真爱生命,开启 ESLint |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
网上已经有很多 JS 隐式类型转换相关的博客, 很多面试者专门复习过此问题, 但依然挡不住面试官一个又一个的无聊小题目~
如果你还在为这些面试题烦恼, 那恭喜你来对了地方!
看完此文你可以完全不需要背诵复杂冗长的 ECMA 规范, 用逻辑即可推理
现在, 我们假装从 JS 设计者的角度来聊聊隐式类型转换, 首先要记住, JS 作者的"初衷"是美好的, 他希望
==
是最顺手最快捷的比较为什么
[] == false
?首先我们知道
[]
和false
一个是对象, 一个是布尔值, 类型不同, 需要类型转换再做比较要注意, JS 中规定, 如果
==
中有布尔值, 只能转换为数字, 那为什么不是转换成字符串呢?因为如果布尔值转换成字符串那就是
'true'
和'false'
, 那这种对比就毫无意义了这也符合我们的常识, 很多语言也是类似的设定, 也就是 Bool 属于一种 Int
所以此问题可以转换成: 为什么
[] == 0
?为什么
[] == 0
?我们知道 Primitive(原值)和非 Primitive 比较, 需要把非 Primitive 转换成 Primitive 才可以
[]
是一个对象, 因此需要toPrimitive()
简单的说, 大部分对象最后都是用
toString()
来转换成 Primitive你也许会问为啥是用 toString 不是 toNumber 之类的呢? 因为每个对象都有 toString 方法,
Object.prototype.toString
, 更上层的对象也会重写 toString 方法继续刨根问底, 为啥每个对象都有 toString 而不是 toNumber 呢?
这就是 JS 对新人友好的地方, JS 的对象都可以打印输出, 自带人性化展示, 在终端上人性化展示, 那当然是用字符串啦, 因此选择用 toString 转换 Primitive 理所因当
我们来看看数组的 toString, 数组的 toString 相当于
join()
所以此问题可以转换成: 为什么
'' == 0
?为了验证我们的想法, 我们来尝试一些更奇葩的对象和字符串的
==
比较({}).toString()
是[object Object]
, 所以'[object Object]' == {}
果然也是 true为什么
'' == 0
?字符串和数字比较会把字符串转换成数字
问题来了, 为什么不是把数字转换成字符串呢? 从设计者的角度可能会这样想
这样对开发者就会很方便
要注意, 字符串转成数字不是用的
parseInt()
或者parseFloat()
, 而是Number()
所以此问题可以继续转换成: 为什么
0 == 0
? 显然就是返回true
转换路程
推理到此结束, 我们回顾一下这个比较的转换规程
[] == false
[] == 0
'' == 0
0 == 0
看到这里我们猛然想明白了为啥 NaN 不能等于自身!
为什么
NaN !== NaN
?我们不妨来看看
'abc' == NaN
做比较的过程因为 NaN 也是数字类型, 所以我们需要把
'abc'
转换为数字'abc' == NaN
相当于Number('abc') == NaN
相当于NaN == NaN
, 如果 NaN 可以等于自身的话, 这种情况就会返回 true那整个隐式转换就乱套了
因此 NaN 不能等于自身也是哑巴吃黄连, 有苦说不出啊
隐式转换的恶果
NaN 不能等于自身是隐式转换最大的恶果
你可以尝试如下操作
有比较的地方, 就会有 NaN 特殊处理, 否则就是不严谨
简单逻辑复杂化, 说的就是你
NaN
, 可以说 "隐式转换一时爽"~为什么
null == 0
是 false 呢 ?两边类型不同, 是不是也要类型转换呢?
要是能转的话确实要转, 但 null 和数字0本身已经是 Primitive 了, 没有机会再走一遍
toPrimitive()
, 因此等号两边始终无法转换成同类型, 只能返回 false为什么
null == undefined
?和上面的问题一样, null 和 undefined 都是 Primitive, 而且也不是字符串或者数字, 转无可转
但 JS 专门规定了
null == undefined
就是返回 true, 属于一种专门的特殊情况The Abstract Equality Comparison Algorithm
为什么
!![]
是true
?这里面不涉及任何
==
比较, 和上面的题目完全是两类题目, 千万不可搞混此题直接判断这个值是不是 Falsy(假值) 即可, 只要不是这几个值, 都是
true
Falsy 的值有
0
,''
,false
,NaN
,null
,undefined
类似的问题
!![] == true
, 因为这个表达式先要计算!![]
, 它已经是 true 了为什么 ESLint 中会各种限制使用
==
?我觉得完全可以理解,
==
虽然也是一种便捷的转换, 但并不符合传统语言的习惯, 工程化企业化的项目不想用这种 "黑魔法" 也是一种正确的选择The text was updated successfully, but these errors were encountered: