转换值

将一个值从一个类型明确地转换到另一个类型通常称为“类型转换(type casting)”,当这个操作隐含地完成时称为“强制转换(coercion)”(根据一个值如何被使用的规则来强制它变换类型)。

注意: 这可能不明显,但是 JavaScript 强制转换总是得到基本标量值的一种,比如 stringnumber、或 boolean。没有强制转换可以得到像 objectfunction 这样的复杂值。第三章讲解了“封箱”,它将一个基本类型标量值包装在它们相应的 object 中,但在准确的意义上这不是真正的强制转换。

另一种区别这些术语的常见方法是:“类型转换(type casting/conversion)”发生在静态类型语言的编译时,而“类型强制转换(type coercion)”是动态类型语言的运行时转换。

然而,在 JavaScript 中,大多数人将所有这些类型的转换都称为 强制转换(coercion),所以我偏好的区别方式是使用“隐含强制转换(implicit coercion)”与“明确强制转换(explicit coercion)”。

其中的区别应当是很明显的:在观察代码时如果一个类型转换明显是有意为之的,那么它就是“明确强制转换”,而如果这个类型转换是做为其他操作的不那么明显的副作用发生的,那么它就是“隐含强制转换”。

例如,考虑这两种强制转换的方式:

  1. var a = 42;
  2. var b = a + ""; // 隐含强制转换
  3. 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 里里外外的专家,也要考虑一个经验没那么丰富的队友在读你的代码时感受如何。对于他们和对于你来说,“明确”或“隐含”的意义相同吗?