js很奇怪的問題,關於加法運算的問題?
console.log(1+ +"2");//3 類型是number
console.log(1+" "); //1 類型是stringconsole.log(1+ +""); //1 類型是number這是為什麼呢
只是規範規定
一個個說
1+ +"2"注意這裡有個空格,不會成為 ++ 運算符,因為與++的parse要求不符,會分開。所以在parse 中是類似是[1, 運算符+,表達式[一元運算符+, 字元串2]]
先進行表達式求值
表達式內是個一元運算符+它的求值是 ES http://www.ecma-international.org/ecma-262/5.1/#sec-11.4.6其中 expr 是字元串2,執行到 2 步驟會被 ToNumber,轉為數值2後,結構變為[1, 運算符+,2]
此時是 ES的+運算 ECMAScript Language Specification
根據 + 運算說明
執行到 8步驟 lprim (左值) rprim(右值)均 ToNumber 後相加,結果為3.1+" "
parse[1, 運算符+,空字元串]同根據 ES的+運算 ECMAScript Language Specification執行到 7 判斷出 rprim 是 String,則lprim 和 rprim 均 ToString 後連接。結果為字元串 「1」.1+ +""parse 同 第一個[1, 運算符+,表達式[一元運算符+, 空字元串]]
先進行表達式求值
表達式內是個一元運算符+它的求值是 ES http://www.ecma-international.org/ecma-262/5.1/#sec-11.4.6其中 expr 是空字元串,執行到 2 步驟會被 ToNumber,轉為數值0後(見注1),結構變為[1, 運算符+,0]
執行到 8步驟 lprim (左值) rprim(右值)均 ToNumber 後相加,結果為1.
【注1】:其中 ToNumber 對 string 的處理需要看ECMAScript Language Specification其中有說A StringNumericLiteral that is empty or contains only white space is converted to +0.
空字元串和只包含空格的轉為 +0 (ES 的0 是帶符號的有+0 和-0)
js的隱式轉換,高程里說了蠻多的。
+運算符在兩邊都是Number類型的時候,會直接運行我們所熟悉的數學加法運算。-運算符亦然。
對於 +運算符 ,兩邊有其一為字元串(String類型),有以下好幾種情況:- 另一邊為String類型的時候,直接連接兩字元串,這不用多說了吧,其實和String類型的concat方法有一樣的效果的。
- 另一邊為Number,Boolean類型的時候,會調用其自身的toString()方法對其進行轉換成相應地字元串,至於這些基本類型為什麼可以使用toString()方法,這又是js底層的一種內部轉換的實現了,不多說,與題無關。
- 另一邊為NULL,undefined類型的時候,由於這些類型無toString方法,內部轉換的時候會使用String()對其進行轉換。
- 另一邊為Object、Function類型時,首先你要知道他們有valueOf和toString這兩種轉換的方法,每個Object和Function類型默認都有toString,而valueOf方法需自己定義,當該對象有valueOf得時候,內部類型轉換的時候會調用valueOf進行轉換,沒有的話會調用toString進行轉換,這就不用舉例子了吧,馬上打開控制台試一下又不是什麼難事。
說完 +運算符,說一下-運算符吧
String類型不能單純使用-運算符進行相減,減法只存在於數學運算,這沒問題吧。所以,當使用-運算符的時候,對於非Number類型都會轉換成Number然後再進行數學運算,對於Boolean,String,Null,nudefined類型會調用Number()對其進行轉換,而對於Object,如上面第4點所說對其先轉換成String類型然後再使用Number()轉換成Number類型。(js真麻煩。。。。
而為什麼1+ +"2"的結果是3呢,在運算時,js先執行 +"2" ,這相當於Number("2"),這也沒什麼好糾結的把,就當做js的語法糖就是了,"+變數" 的處理和-運算符的處理差不多,打開控制台試試吧。
對了,關於@Danilo說提到的 +new Date(),他實際上返回的是從1970.1.1至今的毫秒數,和Date.now()的做法一樣,不過某些低版本瀏覽器不支持Date.now()這個方法,不過可以用+new Date()替代之。以後別寫這種偏門寫法習慣這麼寫的人最好早點開除
別問我為什麼,隱式類型轉換,天知道 JavaScript 什麼時候會不高興,不同引擎反應可能還不一樣。有興趣可以研究下規律,但是最好的解決方案是——不要這樣寫代碼。
====================
看到有人說理解的基礎之上想用就用...我只能說...呵呵...可以測試以下代碼的輸出:
var a = 1;
console.log("2" + a - a);
console.log("2" - a + a);
看看理解了隱式類型轉換後 JavaScript 是不是就真能 make you happy 了...這還只是冰山一角。
====================
再補充一下,問題中的代碼的確沒有出現異常,1+ +"2" === 1+(+"2"),第三個同理,而三者都發生了隱式類型轉換,"2" =&> 2,"" =&> 0。注意兩個 + 號中間要有空格,不然會被當作 ++ 運算符處理,而 ++ 運算符的 left-hand 必須是合法的 expression,1 並不合法,因此會報錯。而且,好在現在主流的代碼壓縮工具會把 1+ +"2" 轉為 1+2,不然簡單粗暴的幹掉空格,鬼知道會發生什麼。
最後我堅持觀點,不要這樣寫代碼!坑死爹不償命!首先我是手機不請自答! 因為藏不住心中的怒火!
這是100px的大字
【不要寫這種代碼,就算真的必須這麼做,請帶上()! 最後別去寫這種!】解答+"" 其實就是 數字0 不要問為什麼!記住就行!js隱式轉換,能讓你哭死!這種東西不要玩,害死人,學也不要學。
想了解為什麼,看犀牛書的隱式轉換。
我猜測,是1++""後面的加號視為+-正負,優先順序高,所以先轉換為0再和前面加,自然是數字。規則是下面這樣的,另外加上 (+"") = Number("") 這樣的強制轉換成number就能得到結果了。至於為什麼會這樣你應該深入了解組織。
很簡單啊,String/Date/Object,前面放個加號,會產生類型轉換,轉成 Number 類型記得以前和某同學一起討論過,印象中還是根正苗紅的 ECMAScript 規範產物,有興趣可以查一下 ECMA 文檔,有詳細說明
至於題主的寫法,其實是這樣的:1 + +"2" =&> 1 + (+"2")這就清晰了這種寫法通過上面截圖能看到,對於 Date 類型,可以很方便取時間戳,兼容性很好噢而且遇到伺服器返回的時候,可以這麼寫:補充:
查了一下 Standard ECMA-262 5.1 Edition / June 2011 ,記憶還是沒偏差的。(順嘴打上了w3c,我不嚴謹了,騷瑞)ECMAScript 說得很明白了,加號後面跟一個操作元,叫 Unary + Operator ,會將操作元轉換為 Number 形式。而隱式類型轉換,則是在加法運算中,左式或右式出現字元串類型時,將其餘表達式轉換為字元串(調用 toString() )一元操作符原文:11.4.6Unary + OperatorThe unary + operator converts its operand to Number type.
The production UnaryExpression : + UnaryExpression is evaluated as follows:
加法運算原文:
- Let expr be the result of evaluating UnaryExpression.
- Return ToNumber(GetValue(expr)).
11.6.1The Addition operator ( + )
The addition operator either performs string concatenation or numeric addition.
The production AdditiveExpression : AdditiveExpression + MultiplicativeExpression is evaluated as follows:
- Let lref be the result of evaluating AdditiveExpression.
- Let lval be GetValue(lref).
- Let rref be the result of evaluating MultiplicativeExpression.
- Let rval be GetValue(rref).
- Let lprim be ToPrimitive(lval).
- Let rprim be ToPrimitive(rval).
- If Type(lprim) is String or Type(rprim) is String, then
- Return the String that is the result of concatenating ToString(lprim) followed by ToString(rprim)
- Return the result of applying the addition operation to ToNumber(lprim) and ToNumber(rprim). See the Note below 11.6.3.
NOTE 1No hint is provided in the calls to ToPrimitive in steps 5 and 6. All native ECMAScript objects except Date objects handle the absence of a hint as if the hint Number were given; Date objects handle the absence of a hint as if the hint String were given. Host objects may handle the absence of a hint in some other manner.
NOTE 2Step 7 differs from step 3 of the comparison algorithm for the relational operators (11.8.5), by using the logical-or operation instead of the logical-and operation.
$.get("url").then(function (d) {
if (d +d.status === 1) {
// do somethings.
} else {
// do other things.
}
});
你是不是連看書都懶得了?
+會觸發類型轉換。
typeof +"" === "number"1、 +『2』轉成數字2,所以1+ +『2』等於32、 1+『 』(空格)字元串 1轉字元串 所以等於"13、 1+ +""(空字元串轉成數字0) 所以等於1
+是一目運算符,在js裡面可用於強制類型轉換,string to number。另外加法在運算的時候如果有字元串,會優先進行字元串連接。
這些嘛屬於前端冷知識的範疇!很多人喜歡用,也有很多人不喜歡用,不過在我看來,如果能少寫兩行代碼為什麼不少寫呢! 很多人說不利於代碼閱讀,其實,作為一個敲代碼的,看到不理解的應該第一時間去console裡面試試,然後再去查查資料什麼的~
放心用吧。ps:還有「12」 | 0 也會返回數字推薦閱讀:
※如何評價前端應用框架 dva?
※如何在 JS 中嵌入 HTML 代碼?
※js浮點數精度問題的前世今生?
※為什麼JS中一個浮點數位或0會去掉小數部分?
※怎樣精確區分這些名詞:庫、插件、組件、控制項、擴展?
TAG:前端開發 | JavaScript | JavaScript語言精粹 |