<p>在網路上或面試題中常常會看到一些「奇怪」的語句,例如</p>
<pre class="brush:php;toolbar:false">{}+{}
// "[object Object][object Object]"
{}+[]
// 0
[]+{}
// "[object Object]"
[]+[]
// ""</pre>
<p>在Javascript中<code>+</code>運算子是個重載運算符,可用於拼接字符串,以及把兩個「數字」相加。至於是哪一種情況要看運算子兩邊參數的類型。 <br>在日常的發展中我們也不會碰到這麼麻煩的事,但要弄清楚總是好的。在規範中巴拉巴拉地說了一堆,簡單來說就是:</p>
<p>1. 對於原生類型,參數中只要有一方是字串,則按字串連接處理,否則按數字相加處理,不是數字的會先轉成數字再相加。 </p>
<p>原生型別有:undefined, null, boolean, number, string。 </p>
<p>以下是一些範例:</p>
<pre class="brush:php;toolbar:false">0 + '1' // '01'
null + 1 // 1
true + 1 // 2
false + 1 // 0
undefined + 2 // NaN, 因为undefined转成Number是NaN</pre>
<p>2. 對於參考類型,則需要先轉換成原生類型,再按上述規則相加。如何轉換在規範中有詳細的說明,但規範看起來有點費力。 簡單來說就是:預設都轉換成字串,要搞特殊的話,請重寫<code>valueOf()</code>方法。 </p>
<p>來個例子:</p>
<pre class="brush:php;toolbar:false">function Complex(a, b) {
this.a = a;
this.b = b;
}
Complex.prototype.valueOf() {
return this.a;
}
new Complex(2, 3) + new Complex(4, 5);
// 6</pre>
<p>但由於Js不支援真正的運算子重載,也就是無法相加得到自訂類型的對象, 所以以上範例在實作程式碼中非常少用。 </p>
<p>不過目前的知識已經足夠回答原先的問題了。但慢著,<code>{}+[]</code> 為什麼和 <code>[]+{}</code>不一樣? 這其實是文法問題。前者相當於:</p>
<pre class="brush:php;toolbar:false">{}
+[]</pre>
<p>其實是兩個句子, <code>[]</code> 轉換成數字是 0。很容易驗證<code>({}+[]) === '[object Object]'</code></p>
<pre class="brush:php;toolbar:false">+[] // 0</pre>
<p>有人可能要問,那<code>new Date()</code> 的<code>valueOf()</code> 不是轉換成數字嗎?為什麼相加結果還是字串型呢? </p>
<pre class="brush:php;toolbar:false">new Date().valueOf();
// 1491904757087
1 + new Date();
// "1Tue Apr 11 2017 18:02:16 GMT+0800 (CST)"</pre>
<p>這是Date類別做了特殊處理, @@toPrimitive, 預設情況下對 <code>Date</code> 的相加以字串方式連接,但比較時則會轉換成數字。 </p>
<pre class="brush:php;toolbar:false">new Date() < new Date('2018-01-01')
// true, 现在是2017</pre><p>將引用類型轉換成原生類型在許多運算元中都有用到,例如<code><</code>, <code>>, 所以有必要對其研究一番, 以下js程式碼大概描述了其行為。 <pre class="brush:php;toolbar:false">/**
* @param input 即要转换的对象
* @preferredType 期望转换成的类型,可以是string或number
*/
function ToPrimitive(input, preferredType) {
if (typeof input !== 'object') {
return input; // 本来就是原生类型
}
var hint = preferredType || 'default';
if (typeof input['@@toPrimitive'] === 'function') { // @@toPrimitive是个内部方法,这里只是示例说明其工作原理
return input['@@toPrimitive'](input, hint); // 这就是为什么Date能特殊处理的原因
}
if (hint === 'string') {
return input.toString();
}
return input.valueOf();
}</pre><p>詳細的請參考規格</p><p class="article fmt article__content"><br></p><p>在網路上或面試題目中常會看到一些「奇怪」的語句,例如</p><pre class="brush:php;toolbar:false">{}+{}
// "[object Object][object Object]"
{}+[]
// 0
[]+{}
// "[object Object]"
[]+[]
// ""</pre><p>在Javascript中<code>+</code>運算子是個重載運算符,可用來拼接字串,以及把兩個「數字」相加。至於是哪一種情況要看運算子兩邊參數的類型。 <br>在日常的發展中我們也不會碰到這麼麻煩的事,但要弄清楚總是好的。在規範中巴拉巴拉地說了一堆,簡單來說就是:</p><p>1. 對於原生類型,參數中只要有一方是字串,則按字串連接處理,否則按數字相加處理,不是數字的會先轉成數字再相加。 </p><p>原生型別有:undefined, null, boolean, number, string。 </p><p>以下是一些範例:</p><pre class="brush:php;toolbar:false">0 + '1' // '01'
null + 1 // 1
true + 1 // 2
false + 1 // 0
undefined + 2 // NaN, 因为undefined转成Number是NaN</pre><p>2. 對於參考類型,則需要先轉換成原生類型,再按上述規則相加。如何轉換在規範中有詳細的說明,但規範看起來有點費力。 簡單來說就是:預設都轉換成字串,要搞特殊的話,請重寫<code>valueOf()</code>方法。 </p><p>來個例子:</p><pre class="brush:php;toolbar:false">function Complex(a, b) {
this.a = a;
this.b = b;
}
Complex.prototype.valueOf() {
return this.a;
}
new Complex(2, 3) + new Complex(4, 5);
// 6</pre><p>但由於Js不支援真正的運算子重載,也就是無法相加得到自訂類型的對象, 所以以上範例在實作程式碼中非常少用。 </p><p>不過目前的知識已經足夠回答原先的問題了。但慢著,<code>{}+[]</code> 為什麼和 <code>[]+{}</code>不一樣? 這其實是文法問題。前者相當於:</p><pre class="brush:php;toolbar:false">{}
+[]</pre><p>其實是兩個句子, <code>[]</code> 轉換成數字是 0。很容易驗證<code>({}+[]) === '[object Object]'</code></p><pre class="brush:php;toolbar:false">+[] // 0</pre><p>有人可能要問,那<code>new Date()</code> 的<code>valueOf()</code> 不是轉換成數字嗎?為什麼相加結果還是字串型呢? </p><pre class="brush:php;toolbar:false">new Date().valueOf();
// 1491904757087
1 + new Date();
// "1Tue Apr 11 2017 18:02:16 GMT+0800 (CST)"</pre><p>這是Date類別做了特殊處理, @@toPrimitive, 預設情況下對 <code>Date</code> 的相加以字串方式連接,但比較時則會轉換成數字。 </p><pre class="brush:php;toolbar:false">new Date() < new Date('2018-01-01')
// true, 现在是2017</pre><p>將引用類型轉換成原生類型在許多運算元中都有用到,例如<code><</code>, <code>>, 所以有必要對其研究一番, 以下js程式碼大概描述了其行為。 <pre class="brush:php;toolbar:false">/**
* @param input 即要转换的对象
* @preferredType 期望转换成的类型,可以是string或number
*/
function ToPrimitive(input, preferredType) {
if (typeof input !== 'object') {
return input; // 本来就是原生类型
}
var hint = preferredType || 'default';
if (typeof input['@@toPrimitive'] === 'function') { // @@toPrimitive是个内部方法,这里只是示例说明其工作原理
return input['@@toPrimitive'](input, hint); // 这就是为什么Date能特殊处理的原因
}
if (hint === 'string') {
return input.toString();
}
return input.valueOf();
}</pre><p class="col-md-8"><br></p><p class="comments-box-content"><br></p>#</pre></pre>
以上是理解Javascript中的“+”運算符的詳細內容。更多資訊請關注PHP中文網其他相關文章!