JavaScriptでは、プリミティブ(文字列、数値など)をオブジェクトのように扱うことができます。それらは、メソッドを呼び出すこともできます。これらについてはすぐに学習しますが、まずプリミティブはオブジェクトではないため、どのように動作するのかを見ていきます(ここでそれをさらに明確にします)。
プリミティブとオブジェクトの主な違いを見てみましょう。
プリミティブ
- プリミティブ型の値です。
- 7つのプリミティブ型があります:
string
,number
,bigint
,boolean
,symbol
,null
そしてundefined
。
オブジェクト
- 複数の値をプロパティとして格納することができます。
- 例えば、
{name: "John", age: 30}
のように、{}
で作成できます。JavaScriptには他の種類のオブジェクトもあります。例えば、関数はオブジェクトです。
オブジェクトの最も優れた点の1つは、関数をそのプロパティの1つとして格納できることです。
let john = {
name: "John",
sayHi: function() {
alert("Hi buddy!");
}
};
john.sayHi(); // Hi buddy!
ここでは、メソッドsayHi
を持つオブジェクトjohn
を作成しました。
日付、エラー、HTML要素などを扱う組み込みオブジェクトがすでにたくさん存在します。それらは異なるプロパティとメソッドを持っています。
しかし、これらの機能にはコストがかかります!
オブジェクトはプリミティブよりも「重い」です。内部機構をサポートするために追加のリソースが必要です。
オブジェクトとしてのプリミティブ
JavaScriptの作成者が直面したパラドックスを紹介します
- 文字列や数値のようなプリミティブでやりたいことはたくさんあります。メソッドを使用してそれらにアクセスできると素晴らしいでしょう。
- プリミティブは可能な限り高速かつ軽量である必要があります。
解決策は少しぎこちないように見えますが、ここにあります
- プリミティブは、依然として望ましい単一の値であるプリミティブです。
- 言語は、文字列、数値、ブール値、およびシンボルのメソッドとプロパティへのアクセスを許可します。
- それを機能させるために、特別な「オブジェクトラッパー」が作成され、追加の機能が提供され、その後破棄されます。
「オブジェクトラッパー」はプリミティブ型ごとに異なり、String
、Number
、Boolean
、Symbol
、およびBigInt
と呼ばれます。したがって、異なるメソッドセットを提供します。
たとえば、大文字のstr
を返す文字列メソッド str.toUpperCase() が存在します。
これがその仕組みです
let str = "Hello";
alert( str.toUpperCase() ); // HELLO
簡単ですね?str.toUpperCase()
で実際に起こることは次のとおりです
- 文字列
str
はプリミティブです。そのため、そのプロパティにアクセスする瞬間に、文字列の値を認識し、toUpperCase()
のような便利なメソッドを持つ特別なオブジェクトが作成されます。 - そのメソッドが実行され、新しい文字列を返します(
alert
で表示されます)。 - 特別なオブジェクトは破棄され、プリミティブの
str
はそのまま残ります。
そのため、プリミティブはメソッドを提供できますが、依然として軽量です。
JavaScriptエンジンは、このプロセスを高度に最適化します。追加のオブジェクトの作成をすべてスキップすることさえあります。しかし、仕様に従い、オブジェクトを作成するかのように動作する必要があります。
数値には独自のメソッドがあります。たとえば、toFixed(n)は数値を指定された精度に丸めます。
let n = 1.23456;
alert( n.toFixed(2) ); // 1.23
より具体的なメソッドについては、数値と文字列の章で見ていきます。
String/Number/Boolean
は内部使用のみJavaのような一部の言語では、new Number(1)
やnew Boolean(false)
のような構文を使用して、プリミティブの「ラッパーオブジェクト」を明示的に作成できます。
JavaScriptでは、歴史的な理由からそれも可能ですが、非常に推奨されません。さまざまな場所で問題が発生します。
例として
alert( typeof 0 ); // "number"
alert( typeof new Number(0) ); // "object"!
オブジェクトはif
で常に真なので、ここではアラートが表示されます。
let zero = new Number(0);
if (zero) { // zero is true, because it's an object
alert( "zero is truthy!?!" );
}
一方、new
なしで同じ関数String/Number/Boolean
を使用することは完全に問題なく、有用なことです。それらは値を対応する型(文字列、数値、またはブール値(プリミティブ))に変換します。
たとえば、これは完全に有効です
let num = Number("123"); // convert a string to number
特別なプリミティブnull
とundefined
は例外です。それらには対応する「ラッパーオブジェクト」がなく、メソッドも提供しません。ある意味、それらは「最もプリミティブ」です。
そのような値のプロパティにアクセスしようとするとエラーが発生します
alert(null.test); // error
まとめ
null
とundefined
を除くプリミティブは、多くの役立つメソッドを提供します。それらについては、今後の章で学習します。- 形式的には、これらのメソッドは一時的なオブジェクトを介して機能しますが、JavaScriptエンジンは内部でそれを最適化するように調整されているため、呼び出すのにコストはかかりません。
コメント
<code>
タグを使用し、数行の場合は<pre>
タグで囲み、10行を超える場合はサンドボックス(plnkr、jsbin、codepen…)を使用してください