转换值
将一个值从某个型别转换至另一个型别的动作,叫做「型别转换(type casting)」。
因为值的使用规则而被迫转型的,叫做「强制转型(coercion)」。
JS强制转型(coercion)的结果永远都会是纯量的基型值。
明确的强制转型:能够从程式码看出型别转换动作是刻意进行的。
隐含的强制转型:型别转换因其他作业而产生较不明显的副作用。
执行b = a + ""
,由于+
的运算子,其中一个运算元是string
的话,那这个运算式就会执行string
的串接动作,而(隐藏)的副作用,就是会将42(number)
转换成"42"(string)
。
至于c = String( a )
,则是很明显地将a
的值明确地换成string
。
以上2者都可以达到相同的效果:42(number)
转换成"42"(string)
。
如果你很清楚执行b = a + ""
的结果,那这个执行对你来说,是「明确」的;但不清楚c = String( a )
的结果,这个执行则算是「隐含」的。
要记住的一点是,我们撰写的程式码,很少是给自己看的。就算已经是专家等级了,但还是得考虑到团队成员的程度,对他们来说,你的「明确」与「隐含」是否是他们能理解的呢?
ToString
将任何非string值强制转型成string表示值。
基型值的转型:null
=>"null"
、undefined
=>"undefined
、"true
=>"true"
如果物件本身拥有自己的toString( )
方法,而这个物件被当作string
使用,那它的toString( )
就会被自动呼叫。
array的toString( )
结果:
输出string,每个值都以" , "隔开。
ToNumber
如果有任何非number值被当作number值来使用,就会进行转换,例如数学运算。
基型值的转型:tru1
=>1
、undefined
=>NaN
、但是null
=>0
。
object和array会先转成他们的基型等效值,如若不是一个number值,会再次转型为number值。
再转型之前,JS会先确认目标值是否有valueOf( )
方法,若有且回传基型值的话,那个值就会被用于强制转型;如果没有valueOf( )
方法,会使用toString( )
方法(如果有的话)。
如果以上2种执行都无法提供基型值的话,就会掷出TypeError。
ToBoolean
在其他程式语言中,1与0分别代表true与false,但在JS中number就是number,boolean就是boolean。可以把1强制转型成true,0强制转型成false(反之亦然),但实际上,他们并不相同。
1并不等于true,0也不等于false。
Falsy值
JS所有的值可以被分为2种:被强制转型为boolean型别后,不是true就是false。
会被称为「falsy(假值的)」的值:
undefinednullfalse+0、-0、NaN" "以上的值,如果转型成boolean会成为flase。
如果某个值不在这清单上,那已较合乎逻辑的想法,我们可以判定它就在另一个清单「truthy」上。
Truthy值
d的结果为true。请注意,以上的值虽然乍看之下会转为false,但实际上,它们的型别都是string,既然如此,结果当然为true。
d的结果仍为true。切记,只要是没在falsy清单的值,都为truthy值。
truthy与flasy的重要性在于,一个值转型成boolean时,会有怎样的行为。
明确转型:Strings <--> Numbers
直接看範例:String( )
方法会把任何值强制转型成string,Number( )
方法则是会把任何值强制转型成number。
以上的方式之所以称为「明确转型」,是因为可以从程式码很明显的看出执行作业的结果。
除了上述的方式之外,也有其他方式能进行「明确转型」:
执行a.toString( )
,从表面看来,toString( )
是执行了「明确转型」,但这里有个「隐含转型」的存在。toString( )
是个方法,所以无法用在像是42这种基型值上。JS会自动地把42「封装」在一个物件包裹器(object wrapper)之中,如此一来,便具有object的行为了,就能呼叫toString( )
。
至于+c
,这个看起来很特别的运算式,只有单一运算元的运算子,不会执行数学运算或string的串接。+
运算子会明确地把它的运算元转型成number值。
-
运算子也会像+
一样转型,但它会反转数值的正负号。且我们不能把2个相邻的符号放在一起(--)
,这样会被解读为递减运算子,应该要在中间加上空格,- -"3.14"
。
如果会与其他运算子紧密相邻,应该就要避免使用单一运算子的方式来进行强制转换,以免造成混淆。
日期转数字
单一+
运算子的另一个用途是将Date object强制转型成number,结果会是那个日期时间值的unix时间戳(从1970年1月1日 00:00:00 UTC 开始,所经过的毫秒数)。
取得当下的时间戳:
有2种非强制转型的方式:
以及ES5新增的,建议使用
明确地:剖析数值字串
将一个string的内容剖析出number的动作,可以达成类似将string强制转换成number的效果,但这种执行与之前讨论的string转型成number还是有所差异。
剖析数值的动作能够接受非数值字元,从左至右剖析,遇到非数值字元便会停止,输出剖析成功的数值。
强制转型无法接受任何非数值字元,转型会失败,产生NaN。
如果对于剖析的对象并无要求是否全部为数值,可以使用parseInt( )
,但若只能接受数字,譬如"42px"不该视为数字的话,那就使用强制转型。
parseInt( )
只能用于string值。如果传入一个非string值,该值会先被强制转型为string,这是一种隐含地强制转型,这是不好的,请避免这种行为。
明确地:* --> Boolean
使用Boolean( )
进行强制转型:
结果为true
结果为false
虽然Boolean( )
可以明确地转型,但并不普遍。
如同+
运算子一样,!
也会强制地将某个值转型成反向的Boolean值,因此我们会使用!!
双否定运算子再做一次反向。
if(...)
叙述式,会强制将值转换为boolean。
上面为三元运算子(ternary operator),会依据a的boolean值,判断指定true或false给b。
表面看起来是明确地强制转换,但实际上,a运算式会隐含地强制转型成boolean,才能进行判断。
就明确转型来说,Boolean(a)
和!!a
都是比较好的选择。
参考来源:
此为You Don't Know JS系列的笔记。