算数

白鹤亮翅

小学算术告诉我们:1 + 1 = 2。在严谨的编程世界里,加法和减法理应是最无害、最可预测的初等数学运算。

当场打脸

一旦进入 JavaScript 的隐式类型转换地界,基础四则运算开始让人怀疑人生:

"11" + 1    // '111'  (加法变成了字符串拼接)
"11" - 1    // 10     (减法怎么又变回纯数学了?!)

true + true // 2      (布尔值还能直接做加法)
true + 2    // 3

见招拆招

ECMAScript 规范对加号(+)与减号(-)定义了完全不同的隐式转换优先级:

  • 减号 -:只有纯数学减法语义。两侧操作数都会无条件执行 ToNumber() 强制转换为数值后再运算;
  • 加号 +:身兼“数字相加”与“字符串拼接”双重职责。如果任意操作数是字符串(或通过 ToPrimitive() 得到字符串),优先执行拼接;仅在双方均为非字符串(如 Boolean 会先被转成 1 和 0)时,才执行数字加法:
Number  + Number  -> addition
Boolean + Number  -> addition
Boolean + Boolean -> addition
String  + Number  -> concatenation
String  + Boolean -> concatenation
String  + String  -> concatenation

避坑防身:在进行算术运算前做显式类型转换(如 Number(val)),或使用 TypeScript 在编译期杜绝此类隐式类型强制转换。