节选
下面部分节选自:《你不懂JS:类型与文法》第四章:强制转换中的 “明确地:Strings <–> Numbers”
除了String(..)和Number(..),还有其他的方法可以把这些值在string和number之间进行“明确地”转换:
var a = 42;
var b = a.toString();
var c = "3.14";
var d = +c;
b; // "42"
d; // 3.14
调用 a.toString()
在表面上是明确的(“toString”意味着“变成一个字符串”是很明白的),但是这里有一些藏起来的隐含性。toString()
不能在像 42
这样的 基本类型 值上调用。所以JS会自动地将42
“封箱”在一个对象包装器中,这样toString()
就可以针对这个对象调用。换句话讲,你可能会叫它“明确的隐含”。
这里的+c
是+
操作符的 一元操作符(操作符只有一个操作数)形式。取代进行数学加法(或字符串连接 —— 见下面的讨论)的是,一元的+
明确地将它的操作数(c
)强制转换为一个number
值。
+c
是 明确的 强制转换吗?这要看你的经验和角度。如果你知道(现在你知道了!)一元+
明确地意味着number
强制转换,那么它就是相当明确和明显的。但是,如果你以前从没见过它,那么它看起来就极其困惑,晦涩,带有隐含的副作用,等等。
注意: 在开源的JS社区中一般被接受的观点是,一元+
是一个 明确的 强制转换形式。
即使你真的喜欢+c
这种形式,它绝对会在有的地方看起来非常令人困惑。考虑下面的代码:
var c = "3.14";
var d = 5+ +c;
d; // 8.14
一元-
操作符也像+
一样进行强制转换,但它还会翻转数字的符号。但是你不能放两个减号--
来使符号翻转回来,因为那将被解释为递减操作符。取代它的是,你需要这么做:- -"3.14"
,在两个减号之间加入空格,这将会使强制转换的结果为3.14
。
这里有另一个疯狂的例子( 一个二元操作符挨着另一个操作符的一元形式):
1 + - + + + - + 1; // 2
当一个一元+
(或-
)紧邻其他操作符时,你应当强烈地考虑避免使用它。虽然上面的代码可以工作,但几乎全世界都认为它是一个坏主意。即使是d = +c
(或者d =+ c
!)都太容易与d += c
像混淆了,而后者完全是不同的东西!
注意: 一元+
的另一个极端使人困惑的地方是,被用于紧挨着另一个将要作为++
递增操作符和--
递减操作符的操作数。例如:a +++b
,a + ++b
,和a + + +b
。更多关于++
的信息,参见第五章的“表达式副作用”。
记住,我们正努力变得明确并 减少 困惑,不是把事情弄得更糟!
理解
关于 1 + - + + + - + 1;
看到的第一印象是很懵的这个要怎么去理解????
后来反复阅读上面的节选部分内容,找到了关键的一句换:
一元-
操作符也像+
一样进行强制转换,但它还会翻转数字的符号。
也就是说:
一元+
操作符会把字符串强制转换为数字
一元-
操作符不仅会把字符串强制转换为数字,还会翻转数字的符号 — 即改变数字的正负
现在再来看这行代码 1 + - + + + - + 1;
可以粗略的把它分为三个部分:数字1
、加法运算符 +
以及强制转换部分- + + + - + 1
根据刚刚理解的转换规则,在看强制转换部分的时候可以把+
暂时忽略(一元+
操作符只会把字符串强制转换为数字),那么只剩下 - - 1
,所以可以很快的得出强制转换的结果为 1
(-
为奇数符号改变,为偶数符号不变),整行代码运行的结果为2
下面这些也就很好理解了:
1 + - 1; // 0
1 + - + + + + - 1; // 2
1 + - + + + - - 1; // 0
1 + - + + + - + + 1; // 2
1 + - + + + + - - + + 1; // 0
1 + - + + + + - + + 1; // 2