web-dev-qa-db-ja.com

JavaScriptが文字列と数字の間のプラス演算子とマイナス演算子を異なる方法で処理するのはなぜですか?

JavaScriptがこのように機能する理由がわかりません。

console.log("1" + 1);
console.log("1" - 1);

1行目は11を出力し、2行目は0を出力します。JavaScriptが1行目を文字列として処理し、2行目を数値として処理するのはなぜですか?

61
Nir

文字列の連結は+で行われるため、Javascriptは最初の数値1を文字列に変換し、「1」と「1」を連結して「11」にします。

文字列に対して減算を実行できないため、Javascriptは2番目の「1」を数値に変換し、1から1を減算してゼロになります。

93

_+_はあいまいです。 「連結」を意味する場合がありますまたは「追加」。一方は文字列であるため、「連結」を意味するものと解釈され、結果は11です(ちなみに、これは幼い頃の私のお気に入りのジョークの1つでした。視覚的に表示:_│┼│ ニ ⊞_)

_-_には、減算という1つの意味しかありません。だから減算します。

この種の問題は、「連結」が_._ではなく_+_であるPHPなどの他の言語には存在せず、あいまいさはありません。 MySQLのような他の言語には、CONCAT(a,b,c...)を代わりに使用する連結演算子さえありません。

33

仕様 が明示的にそうするように指示しているため。ページ75. 11.6.1の手順5〜8と11.6.2の手順5〜7の違いに注意してください。

11.6.1-加算演算子の仕組みを説明します

1-4。 ...

5。 lprimをToPrimitive(lval)とします。

6。 rprimをToPrimitive(rval)とします。

7。 Type(lprim)がStringまたはType(rprim)がStringの場合、

7a。 ToString(lprim)にToString(rprim)を連結した結果である文字列を返します

8。 ToNumber(lprim)およびToNumber(rprim)に加算演算を適用した結果を返します

11.6.2-減算演算子の仕組みを説明します

1-4。 ...

5。 lnumをToNumber(lval)とします。

6。 rnumをToNumber(rval)とします。

7。減算演算をlnumとrnumに適用した結果を返します

Summary追加の場合、ヒントのないプリミティブ値に変換されたオペランドのいずれかが突然文字列になった場合、2番目のオペランドも文字列に変換されます。減算の場合、両方のオペランドが数値に変換されます。

22
Yury Tarabanko

_+_は、数値変数では加算演算子であり、文字列では連結演算子です。

_+_の後に文字列がある場合、Javascriptは_+_を連結演算子として使用し、文字列の周りでできるだけ多くの用語を変換(入力)して、連結できるようにします。それはJavascriptの動作です。 (console.log(23 + 2 + "." + 1 + 5 + "02" + 02);を試した場合、結果は_25.15022_になります。数値_02_は、連結される前に文字列_2_に入力されました。

_-_は減算演算子のみであるため、文字列が指定されると、文字列_"1"_の型を暗黙的に数値_1_に変更します。そうしなかった場合、_"1" - 1_が意味を成す方法はありません。 console.log(23 + 2 + 1 + 5 - "02" + 03);を試した場合、32が得られます-文字列_02_は数値_2_に変換されます。 _-_の後の用語は、数値に変換できる必要があります。 console.log(23 - 2 - "." - 1 - 5 - 02 - "02");を試してみると、NaNが返されます。

さらに重要なことは、console.log(23 + 2 + "." + 1 + 5 - "02" + 03);を試した場合、_26.15_を出力します。ここでは、_-_の前のすべてが文字列として扱われます(文字列_"."_を含むため、 _-_の後の用語は数値として扱われます。

7
dayuloli

JavaScript **には専用の文字列連結演算子はありません。加算演算子+は、オペランドのタイプに応じて、文字列の連結または加算を実行します。

"1" +  1  // "11"
 1  + "1" // "11"
 1  +  1  // 2

連結の反対はありません(私は思う)、減算演算子-はオペランドのタイプに関係なく減算のみを実行します:

"1" -  1  // 0
 1  - "1" // 0
 1  -  1  // 0
"a" -  1  // NaN

** PHPの.演算子とVBの&演算子は専用の文字列連結演算子です。

6
Salman A

標準のEcmaScript 262によると、_+_および_-_演算子は、文字列が含まれる場合に異なる動作をします。最初は、すべての値を文字列に変換します。 2番目は、すべての値を数値に変換します。

標準から:

Type(lprim)がStringまたはType(rprim)がStringの場合、ToString(lprim)にToString(rprim)を連結した結果であるStringを返します

このルールは、式に文字列値がある場合、_+_操作に含まれるすべての値が文字列に変換されることを意味します。 JavaScriptでは、_+_演算子が文字列で使用されると、文字列が連結されます。これが、console.log("5"+1)が「51」を返す理由です。 _1_は文字列に変換され、「5」+「1」が連結されます。

それでも、上記のルールは_-_演算子には適用されません。 _-_を使用している場合、すべての値は標準に従って数値に変換されます(以下を参照)。したがって、この場合、_"5"_は_5_に変換され、_1_が減算されます。

標準から:

5 lnumをToNumber(lval)とします。

6 rnumをToNumber(rval)とします。


標準のEcmaScript 262からのオペレーター定義。

演算子+http://www.ecma-international.org/ecma-262/5.1/#sec-11.6.1 Operator + definition

演算子-http://www.ecma-international.org/ecma-262/5.1/#sec-11.6.2 Operator - definition

3
Giuseppe Pes

プラスと文字列""を使用すると、連結を実行しているため、基本的に文字列を返します。

typeof ("" + 1 + 0)  // string
typeof (1 + 0)  // number

代わりに-を使用すると、文字列の連結が可能なため、数値に変換します。

typeof ("" - 1 + 0) // number
0
GibboK