MENU

JavaScript構文変数プリミティブ

【JavaScript】 プリミティブの奇妙な振る舞いとラッパーオブジェクト

更新日:2021/01/13

 

 

普段から作成しているJavaScriptコード。
しかしプリミティブの性質を考えると、少し奇妙な動きをしていることに気が付きます。

 

今回はプリミティブとオブジェクトの関係についてお伝えします。

 

プリミティブの奇妙な動作

 

JavaScriptのプリミティブは、メソッドやプロパティを持たないデータそのものを指します。

 

しかしプリミティブは、この認識だけでは説明できない奇妙な振る舞いをすることがあります。

 

例えば、次のようなコードです。

 


console.log( "今日は雨です".replace("雨","晴れ") ); // 今日は晴れです

 

"今日は雨です"は文字列プリミティブです。
文字列プリミティブはメソッドを持っていないので、上のコードを実行するとエラーが出るはずです。
しかし、何の問題もなく"今日は晴れです"という結果が返ってきます。

 

少しJavaScriptを学んだ人なら、直感的に「Stringオブジェクトのreplaceメソッドが呼ばれている」と判断することでしょう。

 

しかし、よく考えてみてください。
"今日は雨です"は文字列プリミティブであって、Stringオブジェクトではありません。
どう考えても、replaceメソッドが実行されるのは奇妙な振る舞いなのです。

ラッパーオブジェクト

 

結論から言うと、プリミティブは必要に応じて対応するオブジェクトに変換されます。

 

例えば文字列プリミティブは、Stringオブジェクトに変換されます。

 

この変換する動作は、オブジェクトでプリミティブをラップ(包む)しているように見えることから、「ラッパーオブジェクトに変換する」と呼ぶこともあります。

 

前項のコード例では、文字列リテラルからラッパーオブジェクトに変換されていましたが、プリミティブを代入した変数でも同じように変換動作がおこなわれます。

 


const str = "今日は雨です";
console.log( str.replace("雨","晴れ") ); // 今日は晴れです

 

上のコードのような処理は、いつも普通に使用していますよね。
実はそれも、よく考えると奇妙な動作だったわけです。

 

 

※オブジェクトはプリミティブではありませんが、JavaScriptの内部での変換対象です。実際にはそのまま返しています。

余談:実際は変換していないかもしれない

 

ラッパーオブジェクトへの変換は、かなり効率が悪いです。

 

例えば次のコードは、同じ文字列に対して10000回も変換操作をおこなっています。

 


for( let i = 0 ; i < 10000 ; i ++){
   "今日は雨です".replace("雨","晴れ");
}

 

どれくらい遅いのか気になって、実際のコードで速度を計測する人もいるかもしれません。

 

しかし、JavaScriptの仕様書を元にブラウザなどへ実装する際、仕様書よりも効率的なアルゴリズムがあるならそちらを適用することが許されています。

 

つまり動作が正しく行われるなら、いちいち変換しなくてもいいのです。

 

もちろん今使っているブラウザは、仕様書に書かれている通りに毎回変換しているかもしれません。
効率を上げるために、オリジナルの処理を実装しているかもしれません。

 

そんな状況なので、変換しているという前提で速度計測するのは、あまり意味がないかもしれませんね。

記事の内容について

 

こんにちはけーちゃんです。
説明するのって難しいですね。


「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。

そんなときは、ご意見もらえたら嬉しいです。

ご意見はこちら。
https://affi-sapo-sv.com/info.php

【お願い】

お願い

■このページのURL


■このページのタイトル


■リンクタグ



プリミティブと対応するラッパーオブジェクト一覧

プリミティブ

ラッパーオブジェクト

Undefined なし(TypeError例外)
Null なし(TypeError例外)
真偽値(論理値) Boolean
数値 Number
文字列 String
シンボル Symbol
長整数 BigInt
オブジェクト 同じオブジェクト