JS 隐式类型转换

看完此文你可以完全不需要背诵复杂冗长的 ECMA 规范, 用逻辑即可推理,现在, 我们假装从 JS 设计者的角度来聊聊隐式类型转换, 首先要记住, JS 作者的”初衷”是美好的, 他希望 == 是最顺手最快捷的比较

[]==false// true 
!![]==true// true 
!!''==false// true
[1]=='1'// true 
''==0// true 
''==false// true
[1]==true// true 
null==0// false
null==''// false

为什么 [] == false ?

首先我们知道 [] 和 false 一个是对象, 一个是布尔值, 类型不同, 需要类型转换再做比较,要注意, JS 中规定, 如果 == 中有布尔值, 只能转换为数字, 那为什么不是转换成字符串呢?
因为如果布尔值转换成字符串那就是 ‘true’ 和 ‘false’, 那这种对比就毫无意义了,这也符合我们的常识, 很多语言也是类似的设定, 也就是 Bool 属于一种 Int
所以此问题可以转换成:

为什么 [] == 0?

我们知道 Primitive(原值)和非 Primitive 比较, 需要把非 Primitive 转换成 Primitive 才可以
[] 是一个对象, 因此需要 toPrimitive()
简单的说, 大部分对象最后都是用 toString() 来转换成 Primitive

继续刨根问底, 为啥每个对象都有 toString 而不是 toNumber 呢?

这就是 JS 对新人友好的地方, JS 的对象都可以打印输出, 自带人性化展示, 在终端上人性化展示, 那当然是用字符串啦, 因此选择用 toString 转换 Primitive 理所因当
我们来看看数组的 toString, 数组的 toString 相当于 join()

[].toString()   // '' 
[1].toString()  // '1'  
[1,2,3,4].toString()  // '1,2,3,4'

所以此问题可以转换成: 为什么 ‘’ == 0 ?

为了验证我们的想法, 我们来尝试一些更奇葩的对象和字符串的 == 比较

[1]=='1'// true  '[object Object]'=={}// true

({}).toString() 是 [object Object], 所以 ‘[object Object]’ == {} 果然也是 true

为什么 ‘’ == 0 ?

字符串和数字比较会把字符串转换成数字(都转成数字能处理的复杂场景更多, 容错性更高!)

'  1  '==1.0// true  '12.10'==12.1// true

这样对开发者就会很方便 要注意, 字符串转成数字不是用的 parseInt() 或者 parseFloat(), 而是 Number()

Number('')  // 0  
Number('abc')// NaN

所以此问题可以继续转换成: 为什么 0 == 0? 显然就是返回 true
推理到此结束, 我们回顾一下这个比较的转换规程

  1. [] == false
  2. [] == 0
  3. ‘’ == 0
  4. 0 == 0
    看到这里我们猛然想明白了为啥 NaN 不能等于自身!

为什么 NaN !== NaN?

我们不妨来看看 ‘abc’ == NaN 做比较的过程
因为 NaN 也是数字类型, 所以我们需要把 ‘abc’ 转换为数字
‘abc’ == NaN 相当于 Number(‘abc’) == NaN 相当于 NaN == NaN, 如果 NaN 可以等于自身的话, 这种情况就会返回 true
那整个隐式转换就乱套了
因此 NaN 不能等于自身也是哑巴吃黄连, 有苦说不出啊

为什么 null == 0 是 false 呢 ?

两边类型不同, 是不是也要类型转换呢?
要是能转的话确实要转, 但 null 和数字0本身已经是 Primitive 了, 没有机会再走一遍 toPrimitive(), 因此等号两边始终无法转换成同类型, 只能返回 false

为什么 null == undefined ?

和上面的问题一样, null 和 undefined 都是 Primitive, 而且也不是字符串或者数字, 转无可转
但 JS 专门规定了 null == undefined 就是返回 true, 属于一种专门的特殊情况

为什么 !![] 是 true?

这里面不涉及任何 == 比较, 和上面的题目完全是两类题目, 千万不可搞混
此题直接判断这个值是不是 Falsy(假值) 即可, 只要不是这几个值, 都是 true
Falsy 的值有 0, ‘’, false, NaN, null, undefined
类似的问题 !![] == true, 因为这个表达式先要计算 !![], 它已经是 true 了

为什么 ESLint 中会各种限制使用 ==?

我觉得完全可以理解, == 虽然也是一种便捷的转换, 但并不符合传统语言的习惯, 工程化企业化的项目不想用这种 “黑魔法” 也是一种正确的选择。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,198评论 6 514
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,334评论 3 398
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,643评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,495评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,502评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,156评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,743评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,659评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,200评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,282评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,424评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,107评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,789评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,264评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,390评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,798评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,435评论 2 359

推荐阅读更多精彩内容