JavaScript を使用すると、プリミティブ (文字列、数値など) をオブジェクトであるかのように操作できます。また、それ自体を呼び出すメソッドも提供します。これらについてはすぐに学習しますが、最初にそれがどのように機能するかを見てみましょう。もちろん、プリミティブはオブジェクトではないからです (ここでさらに明確にします)。
プリミティブとオブジェクトの主な違いを見てみましょう。
原始的な
プリミティブ型の値です。
7 つのプリミティブ型があります: string
、 number
、 bigint
、 boolean
、 symbol
、 null
、およびundefined
。
オブジェクト
複数の値をプロパティとして保存できます。
{}
を使用して作成できます (例: {name: "John", age: 30}
。 JavaScript には他の種類のオブジェクトもあります。たとえば、関数もオブジェクトです。
オブジェクトの最も優れた点の 1 つは、関数をプロパティの 1 つとして保存できることです。
ジョン = { とします 名前:「ジョン」、 SayHi: function() { alert("やあ、相棒!"); } }; ジョン.sayHi(); // こんにちは、相棒!
ここでは、メソッドsayHi
を使用してオブジェクトjohn
作成しました。
日付、エラー、HTML 要素などを処理するオブジェクトなど、多くの組み込みオブジェクトがすでに存在します。それらには、さまざまなプロパティとメソッドがあります。
ただし、これらの機能にはコストがかかります。
オブジェクトはプリミティブよりも「重い」です。内部機構をサポートするには追加のリソースが必要です。
JavaScript の作成者が直面するパラドックスは次のとおりです。
文字列や数値など、プリミティブを使ってやりたいことはたくさんあります。メソッドを使用してアクセスできると便利です。
プリミティブは可能な限り高速かつ軽量である必要があります。
解決策は少し厄介に見えますが、次のとおりです。
原始的は依然として原始的です。必要に応じて単一の値。
この言語を使用すると、文字列、数値、ブール値、記号のメソッドとプロパティにアクセスできます。
これを機能させるには、追加の機能を提供する特別な「オブジェクト ラッパー」が作成され、その後破棄されます。
「オブジェクト ラッパー」はプリミティブ型ごとに異なり、 String
、 Number
、 Boolean
、 Symbol
、 BigInt
と呼ばれます。したがって、それらはさまざまなメソッドのセットを提供します。
たとえば、大文字のstr
を返す文字列メソッド str.toUpperCase() が存在します。
仕組みは次のとおりです。
let str = "こんにちは"; アラート( str.toUpperCase() ); // こんにちは
シンプルですよね? str.toUpperCase()
で実際に何が起こるかは次のとおりです。
文字列str
プリミティブです。そのため、そのプロパティにアクセスした瞬間に、文字列の値を認識し、 toUpperCase()
などの便利なメソッドを備えた特別なオブジェクトが作成されます。
このメソッドが実行され、新しい文字列が返されます ( alert
で表示)。
特別なオブジェクトは破棄され、プリミティブstr
だけが残ります。
したがって、プリミティブはメソッドを提供できますが、依然として軽量です。
JavaScript エンジンはこのプロセスを高度に最適化します。追加のオブジェクトの作成をまったくスキップすることもあります。ただし、仕様を遵守し、仕様を作成したかのように動作する必要があります。
数値には独自のメソッドがあります。たとえば、 toFixed(n) は数値を指定された精度に丸めます。
n = 1.23456 とします。 アラート( n.toFixed(2) ); // 1.23
より具体的なメソッドについては、「数値と文字列」の章で説明します。
コンストラクターString/Number/Boolean
は内部使用のみです
Java などの一部の言語では、 new Number(1)
やnew Boolean(false)
のような構文を使用して、プリミティブの「ラッパー オブジェクト」を明示的に作成できます。
JavaScript では、歴史的な理由からこれも可能ですが、あまりお勧めできません。いくつかの場所で事態がおかしくなるでしょう。
例えば:
アラート( typeof 0 ); // "番号" alert( 新しい番号のタイプ(0) ); // "物体"!
if
ではオブジェクトは常に true であるため、ここでアラートが表示されます。
ゼロ = 新しい数値(0) とします。 if (zero) { // ゼロはオブジェクトなので true alert( "ゼロは真実だ!?" ); }
一方、同じ関数String/Number/Boolean
new
なしで使用することはまったく問題なく便利です。これらは、値を対応する型、つまり文字列、数値、またはブール値 (プリミティブ) に変換します。
たとえば、これは完全に有効です。
let num = Number("123"); // 文字列を数値に変換します
null/未定義にはメソッドがありません
特殊なプリミティブのnull
とundefined
は例外です。これらには、対応する「ラッパー オブジェクト」がなく、メソッドも提供されません。ある意味、「最も原始的な」ものです。
このような値のプロパティにアクセスしようとすると、次のエラーが発生します。
アラート(null.test); // エラー
null
とundefined
を除くプリミティブには、多くの便利なメソッドが用意されています。これらについては次の章で学習します。
正式には、これらのメソッドは一時オブジェクトを介して機能しますが、JavaScript エンジンは内部で最適化するように適切に調整されているため、呼び出しにコストはかかりません。
重要度: 5
次のコードを考えてみましょう。
let str = "こんにちは"; str.test = 5; アラート(str.test);
どう思いますか?うまくいきますか?何が表示されるのでしょうか?
実行してみてください:
let str = "こんにちは"; str.test = 5; // (*) アラート(str.test);
use strict
たかどうかに応じて、結果は次のようになります。
undefined
(厳密モードなし)
エラー (厳密モード)。
なぜ?行(*)
で何が起こっているかを再現してみましょう。
str
のプロパティにアクセスすると、「ラッパー オブジェクト」が作成されます。
strict モードでは、書き込みはエラーになります。
それ以外の場合、プロパティを使用した操作が続行され、オブジェクトはtest
プロパティを取得しますが、その後「ラッパー オブジェクト」が消えるため、最後の行str
にはプロパティの痕跡がありません。
この例は、プリミティブがオブジェクトではないことを明確に示しています。
追加のデータを保存することはできません。