开篇
JS作为一门动态语言十分灵活,但是伴随而来的弱类型隐式转化的问题让我们十分头疼。
隐式作为一个大课题,很难用一个很简短的篇幅把JS的隐式转换讲解的十分清楚。所以我选择用多次少量的策略进行梳理,争取让你每看完一篇都会有加深对于JS隐式转换的理解。
一元操作符
说到隐式转换,就不得不提操作符了,绝大多数的隐式转换都与操作符有关。我们就从最简单的一元操作符开始我们的隐式转换探索之旅吧! gogogo!
先来一串+
操作符的基础实践:
let n = 1
let s1 = '2'
let s2 = 'z'
let o = {valueOf: function() {return -1}
}n = +n // 值不变
s1 = +s1 // 值变为 2
s2 = +s2 // 值变为 NaN
o = +o // 值变为 -1
由上面的代码可以看到,使用+
操作符后,使用效果会像Number()
转型函数一元进行解析。
而Number()的转化规则就是一元操作符隐式转化的精髓所在。
(开始划重点!
Number()的转化规则如下:
- 数字不变
true
和false
分别转化为0
和1
null
返回0
undefined
返回NaN
string
比较复杂- 如果为空,则返回
0
- 如果是数字(包括整型,浮点数,十六进制),则忽略前导0转化为对应十进制数字
- 如果非上述格式,则返回NaN
- 如果为空,则返回
- 如果是对象,则首先调用valueOf方法,然后按照前面的规则转换,如转换结果还是对象(非原始值),则再调用对象的toString方法。
虽然红宝书中描述为“如果是对象,则首先调用valueOf方法转换返回的值,如果为NaN,则再进行toString方法”但是据我实践发现貌似此处的描述并不准确,或者谁来跟我讲讲
既然我们知道了+
的转换规则,那么可以拓展来验证一下上面的规则,我们这里主要对于对象进行探究
PS: 没有记住规则不要紧,可以按照上面的规则走,多来几次就明白了~
let o1 = {valueOf: function() {console.log('执行valueOf')return 'a'},toString: function() {console.log('执行toString')return -1}
}o1 = +o1 // 执行valueof NaNlet o2 = {valueOf: function() {console.log('执行valueOf')return {}},toString: function() {console.log('执行toString')return -1}
}o2 = +o2 // 执行valueof 执行toString -1let o3 = {valueOf: function() {console.log('执行valueOf')return []},toString: function() {console.log('执行toString')return -1}
}o3 = +o3 // 执行valueof 执行toString -1let o4 = {valueOf: function() {console.log('执行valueOf')return function () {}},toString: function() {console.log('执行toString')return -1}
}o4 = +o4 // 执行valueof 执行toString -1let o5 = []
o5 = +o5 // 0let o6 = function() {}
o6 = +o6 // NaN
关于最后的o5,o6的结果我们要解释一下。不要忘记Array
和Function
也是对象哦,所以他们的执行顺序应该是下面这样的。
+o5 Array的执行顺序:
o5.valueOf()
返回[]
,此时[]
还是个Array对象,于是接下来执行[].valueOf().toString()
[].valueOf().toString()
返回""
Number("")
返回0
+o6 Function的执行顺序:
o6.valueOf()
返回function() {}
,此时还是个Function
对象,于是继续执行toString()
o6.valueOf().toString()
返回"function() {}"
Number("function() {}")
返回NaN
同样的,-
作为一个二元操作符也是与上面的执行类似,不过要注意-
是会取负的哦~
总结
今天我们学习到了一元运算符带来的隐式转换,主要要记得
Number()
的转换规则(尤其是对象)
今日习题:
{}+[]
在Chrome控制台打出的结果是?
小提示:Chrome控制台中前面的{}
会被当成空代码块哦
作者想说的
- 希望大家看了可以提一些建议~ 嘿嘿嘿
- MacbookPro任务进度(2/2)
- 配图是女朋友拍的
- 转载请注明出处,告诉我一下我会很开心~
今天总算是开了一个隐式转换类型的头哈哈哈 ,当然写这方面也是因为自己想要更加深入的了解JavaScript。可能很多人会觉得这种情况我要知道干嘛,业务里面又用不到。
之前的我也这么想过。
但是,我逐渐发现,深入了解语言的特性,可以让自己对于代码的掌控能力越强,出现的BUG也越少,就算出现BUG了定位的效率也越来越高。其中滋味只能自己体会啦~(当然,写之前一定一定要自己梳理清楚整体逻辑和细节,尤其是复杂且紧急的需求,否则你就会留下深深的大坑。
高能预警
下篇不出意外的话应该还是隐式转换(毕竟是个大课题啊哈哈哈) 透露几个下期的关键词
关键字:原始值、valueOf、toPrimitive、==
下期更精彩哦~