2017-04-06 104 views
1

在javascript中,當使用加號(+)連接字符串和 另一個變量時,如果該變量不是string,則該變量將隱式調用它的toString方法。爲了驗證這一點,我創建了一個名爲Apple的構造函數。爲什麼修改Number.prototype.toString不起作用?

function Apple(name) { 
    this.name = name; 
} 

Apple.prototype.toString = function() { 
    console.log('Apple.prototype.toString called.'); 
    return this.name; 
}; 

var apple = new Apple('Thai apple'); 
var msg = apple + ' tastes good.' 
console.log(msg) 

它的工作原理如我所料:計算apple + ' tastes good'時, Apple.prototype.toString被調用。 然後我在Number類型上做了類似的實驗。

Number.prototype.num2str = Number.prototype.toString; 
Number.prototype.toString = function() { 
    console.log('new Number.prototype.toString called.'); 
    return this.num2str(); 
} 

var msg = 'num = ' + 123; 
console.log(msg); 

運行後,我注意到沒有調用Number.prototype.toString。 我很困惑。爲什麼它不像前面的例子那樣工作?

+1

哦;對不起,我會刪除我的評論,然後〜 –

回答

4

爲什麼它不像上一個例子那樣工作?

toString如果該值是一個對象僅稱爲(但是參見下文)。 123不是一個對象,它是一個原始的(數字)值。將原始值轉換爲字符串值遵循不同的規則。請參閱ES2016規範中的§7.1.12,以及§7.1.12.1具體數字(這裏引用的時間太長)以瞭解值如何轉換爲字符串。

當使用+運算符時,原始值是而不是強制轉換爲對象。


但是,即使你創造了多項對象這是行不通的。這是因爲toString實際上並沒有被稱爲數字對象。這是爲什麼?

When performing additio N,以下步驟發生:

[...]
5.讓lprim是什麼? ToPrimitive(lval)。
6.讓rprim是? ToPrimitive(rval)。
[...]

兩個值被轉換爲它們被轉換爲一個數字或字符串特別之前第一原始值(原始值可以是一個字符串,數字,布爾值nullundefined )。
對象轉換爲原始值,這種方式最終將首先調用valueOf。只有該函數的返回值爲而非 a 原始值將調用toString

由於new Number(123).valueOf()返回一個原始值,因此不會調用toString

這裏就是你們的榜樣調整valueOf

Number.prototype.valueOf = function() { 
 
    console.log('new Number.prototype.valueOf called.'); 
 
    return 'something'; 
 
} 
 

 
var msg = 'num = ' + new Number(123); 
 
console.log(msg);


注:toStringvalueOf實際上是將對象轉換爲字符串/數字/圖元的過時的方式。自ES6以來,新的方法是調用對象的@@toPrimitve方法。只有在不存在的情況下,纔會調用toStringvalueOf(請參閱§7.1.1 ToPrimitive)。