2017-10-09 37 views
1

根據我的理解,如果一個對象具有valueOf函數,它將在需要將對象轉換爲原語時使用。如果一個對象具有toString函數,那麼當對象需要轉換爲字符串時將使用它。因此,當您使用+時,應首先使用valueOf(如果存在),然後使用toString爲什麼Date會像其他算術運算符一樣使用+和相似數字來處理字符串?

這就是它似乎做的:

var obj1 = { 
    valueOf:() => 0 
}; 

var obj2 = { 
    toString:() => 'a' 
}; 

var obj3 = { 
    valueOf:() => 0, 
    toString:() => 'a' 
}; 

obj1 + obj1; // -> 0 
obj2 + obj2; // -> 'aa' 
obj3 + obj3; // -> 0 

現在日期正在實施兩個valueOftoStringobj3但是當你做你date + date得到一個字符串!
使用任何其他算術運算符會將日期視爲數字進行操作並返回有效數字。

下面是一些代碼來證明我的困惑:如果第一個操作數是一個字符串

var date = new Date(2017,1,1); 

date - date; // -> 0 
date * date: // -> 2.20790950849296e+24 
date/date; // -> 1 
date % date; // -> 0 
date + date; // -> "Wed Feb 01 2017 00:00:00 GMT+0100 (CET)Wed Feb 01 2017 00:00:00 GMT+0100 (CET)" 
+0

'valueOf' /'toString'首選項僅適用於標準對象,不幸的是日期是一個異常。當然,這對於'+'更令人困惑,它不知道它是否應該將它的參數轉換爲數字或字符串。 – Bergi

+0

行爲可追溯到[* ToPrimitive *](http://ecma-international.org/ecma-262/8.0/#sec-toprimitive),默認提示是除日期和符號以外的所有內置函數的編號。主機對象也可能使用不同的提示。這將是限制性的,如果提示總是數字,字符串是有意義的日期,因爲你可能想寫'今天是'+新日期()'。 – RobG

+0

從用戶的角度來看,字符串和數字都是有意義的。你也可以想'new Date()+ 1000'。但是對於數字來說應該有什麼保證是與其他算術運算符的一致性。這就是爲什麼我發現它贏得那場戰鬥的奇怪。 – Ghetolay

回答

0

那是因爲Date有一個異國情調的@@toPrimitive它喜歡字符串數字。見#[email protected]@toprimitive

Date對象,是中內置的ECMAScript對象,他們 對待「默認」的獨特等價於「字符串」,其他所有內置 的ECMAScript對象對待「默認」爲等價到「號碼」。

+0

這種外來行爲的任何理性原因? – Ghetolay

+0

你正在用javascript寫作,並想知道不規則的反直覺行爲?我不知道這些人在想什麼,但是這可能是一些遺留的原因,因爲後向兼容性原因,現在不會改變。 – ASDFGerte

+0

Date是「獨特」的事實並不例外。符號對象也是唯一的,因爲提示被忽略。關於日期的評論只是指出了它的區別。 – RobG

0

+運營商將充當一個JS串接。由於date會生成一個字符串,因此在這種情況下它將充當連接器。

+1

「*由於日期產生一個字符串*」 - 但爲什麼呢? 'date.valueOf()'產生一個數字。 – Bergi

0

一個對象可以被轉換爲原始值與Symbol.toPrimitive屬性(用作函數值)的幫助。

該函數的調用與字符串參數暗示,它指定了結果原始值的優選類型。提示參數可以是「數字」,「字符串」和「默認」中的一個。

語法Date對象Date()[Symbol.toPrimitive](hint);

如果提示是 「串」 或 「默認」,@@ toPrimitive試圖調用toString方法。如果toString屬性不存在,它會嘗試調用valueOf方法,如果valueOf不存在,則@@ toPrimitive將引發TypeError。

如果提示是「數字」,@@ toPrimitive首先嚐試調用valueOf,如果失敗,則調用toString。

var date = new Date(2017,1,1); 
 

 
console.log('hint is "number":',+date + +date); // using unary plus operator 
 
console.log('hint is "default":',date + date); // no hint (falls to hint == 'string') 
 
console.log('hint is "string":',`${date + date}`); // using template literals

+運算符是所有算術運算符中最混亂的。沒有提示將Date實例轉換爲數字,它充當字符串連接器

+0

問題變成爲什麼是默認提示字符串而不是數字? – Ghetolay

+1

我們假設默認值是數字。然後問題變成爲什麼是默認的提示號碼,而不是字符串:)我希望你看到我要去的地方...日期的默認字符串更加方便/實用,你可以格式化並以你想要的方式顯示它。 (你可以說這是一個概念選擇) – taha

+0

也許這是基於觀點的,但在我看來,一個數字是更合乎邏輯和實用的方式。日期只是一個數字,並且它被評估爲所有算術運算符**的數字,**除+以外。 – Ghetolay

相關問題