转换值
将一个值从一个类型明确地转换到另一个类型通常称为“类型转换(type casting)”,当这个操作隐含地完成时称为“强制转换(coercion)”(根据一个值如何被使用的规则来强制它变换类型)。
注意: 这可能不明显,但是 JavaScript 强制转换总是得到基本标量值的一种,比如 string
、number
、或 boolean
。没有强制转换可以得到像 object
和 function
这样的复杂值。第三章讲解了“封箱”,它将一个基本类型标量值包装在它们相应的 object
中,但在准确的意义上这不是真正的强制转换。
另一种区别这些术语的常见方法是:“类型转换(type casting/conversion)”发生在静态类型语言的编译时,而“类型强制转换(type coercion)”是动态类型语言的运行时转换。
然而,在 JavaScript 中,大多数人将所有这些类型的转换都称为 强制转换(coercion),所以我偏好的区别方式是使用“隐含强制转换(implicit coercion)”与“明确强制转换(explicit coercion)”。
其中的区别应当是很明显的:在观察代码时如果一个类型转换明显是有意为之的,那么它就是“明确强制转换”,而如果这个类型转换是做为其他操作的不那么明显的副作用发生的,那么它就是“隐含强制转换”。
例如,考虑这两种强制转换的方式:
var a = 42;
var b = a + ""; // 隐含强制转换
var c = String( a ); // 明确强制转换
对于 b
来说,强制转换是隐含地发生的,因为如果与 +
操作符组合的操作数之一是一个 string
值(""
),这将使 +
操作成为一个 string
连接(将两个字符串加在一起),而 string
连接的 一个(隐藏的)副作用 将 a
中的值 42
强制转换为它的 string
等价物:"42"
。
相比之下,String(..)
函数使一切相当明显,它明确地取得 a
中的值,并把它强制转换为一个 string
表现形式。
两种方式都能达到相同的效果:从 42
变成 "42"
。但它们 如何 达到这种效果,才是关于 JavaScript 强制转换的热烈争论的核心。
注意: 技术上讲,这里有一些在语法形式区别之上的,行为上的微妙区别。我们将在本章稍后,“隐含:Strings <—> Numbers”一节中仔细讲解。
“明确地”、“隐含地”、或“明显地”和“隐藏的副作用”这些术语,是 相对的。
如果你确切地知道 a + ""
是在做什么,并且你有意地这么做来强制转换一个 string
,你可能感觉这个操作已经足够“明确”了。相反,如果你从没见过 String(..)
函数被用于 string
强制转换,那么对你来说它的行为可能看起来太过隐蔽而让你感到“隐含”。
但我们是基于一个 大众的,充分了解,但不是专家或 JS 规范爱好者的 开发者的观点来讨论“明确”与“隐含”的。无论你的程度如何,或是没有在这个范畴内准确地找到自己,你都需要根据我们在这里的观察方式,相应地调整你的角度。
记住:我们自己写代码而也只有我们自己会读它,通常是很少见的。即便你是一个精通 JS 里里外外的专家,也要考虑一个经验没那么丰富的队友在读你的代码时感受如何。对于他们和对于你来说,“明确”或“隐含”的意义相同吗?