JavaScriptの'1'+2の挙動をECMAScriptから読み解く

に公開

はじめに

JavaScriptの文字列と数字を結合すると文字列になりますが、今回はこれをECMAScriptから簡単に読み解いていきます。

簡易実験

まずはnodeで加算の動きを確認してみます。

> '1' + 2        // "12"(どちらかが String → 連結)
'12'
> 1 + '2'        // "12"
'12'
> '1' + 2n       // "12"(BigInt も ToString される)
'12'
> 1n + '2'       // "12"
'12'
> 1n + 2         // TypeError(数値演算に進み、型混在で例外)
Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions
> 'a' + Symbol() // TypeError(ToString(Symbol) が例外)
Uncaught TypeError: Cannot convert a Symbol value to a string
> new Date() + 1 // 文字列連結されやすい(Date は string ヒント扱い)
'Sat Nov 08 2025 19:29:21 GMT+0900 (日本標準時)1'

ECMAScriptから確認

加算について、ECMAScriptからどういう仕様になっているのかを簡単に確認します。
確認したURLは下記です。
https://tc39.es/ecma262/2025/multipage/ecmascript-language-expressions.html#sec-applystringornumericbinaryoperator
の「If lPrim ...」の部分は「どちらかのオペランドが文字列型である場合」と訳すことができ、文字列かつ演算子の「+」が登場した際にはこの条件に当てはまります。
そこから「lStr と rStr の文字列連結を返す。」という条件に当てはまり、結果として文字列を返す挙動になります。

V8(Google/Chrome・Node.js)から確認

簡単に図示

今回確認した場所のフロー図です。

簡単な調査(参考)

バイトコードでADD命令が入ると考え、下記に辿り着きました。
https://chromium.googlesource.com/v8/v8/%2B/1769f892cef0822e6a8b5334e2ad909a0c33e906/src/interpreter/interpreter-generator.cc#900
呼ばれている関数は下記です。
https://chromium.googlesource.com/v8/v8.git/%2B/master/src/interpreter/interpreter-generator.cc#983
https://chromium.googlesource.com/v8/v8.git/%2B/master/src/interpreter/interpreter-generator.cc#967
また、下記が呼ばれています。
https://chromium.googlesource.com/v8/v8.git/%2B/refs/heads/11.2.67/src/ic/binary-op-assembler.cc#22
https://chromium.googlesource.com/v8/v8.git/%2B/refs/heads/11.2.67/src/ic/binary-op-assembler.cc#196
Builtinsは下記に定義があります。
https://chromium.googlesource.com/v8/v8/+/a438bc4166e0b0a29b94ac204649f6ed673aba03/src/builtins
https://chromium.googlesource.com/v8/v8/%2B/44989e310c418c29ef86c63e8c44525cca4abaa5/src/builtins/base.tq#868
連結自体は下記です。
https://chromium.googlesource.com/v8/v8/%2B/4213af64b6b9c9d04be89303169562460d38df84/src/code-stub-assembler.cc#4586

まとめ

今回は、JavaScriptの加算を少し深掘りしてみました。
学習の補助になると幸いです。

参考

Discussion