MDN]1から引用しています。
文字列リテラル(二重引用符または一重引用符で示される)および文字列 文字列リテラル(二重引用符で表示)と、コンストラクタ以外のコンテキストで(つまり は、プリミティブ文字列です。JavaScriptは自動的に プリミティブをStringオブジェクトに変換します。 プリミティブな文字列に対して、Stringオブジェクトのメソッドを使用することができます。このため、プリミティブな文字列に対して プリミティブな文字列に対してメソッドを呼び出したり、プロパティを参照するような場面で が発生した場合、JavaScriptは自動的に文字列プリミティブをラップして メソッドを呼び出したり、プロパティを参照したりします。
つまり、文字列プリミティブに対する操作(メソッド呼び出し)は、文字列オブジェクトに対する操作よりも遅くなるはずだと(論理的に)考えたのです。
しかし、この テストケース では、結果は逆になっています。コードブロック-1はコードブロック-2よりも高速に実行されます(両コードブロックは以下の通り)。
コードブロック-1 :
var s = '0123456789';
for (var i = 0; i < s.length; i++) {
s.charAt(i);
}
コードブロック-1 : {{19124099}}} コードブロック-2 :**
var s = new String('0123456789');
for (var i = 0; i < s.length; i++) {
s.charAt(i);
}
ブラウザによって結果は異なりますが、常にコードブロック-1の方が速いです。なぜ、コードブロック-1の方がコードブロック-2より速いのか、誰かこれを説明してください。
もし new
を使用した場合、Object のインスタンスを作成することを明示的に示していることになります。したがって、 new String
は String プリミティブをラップした Object を生成することになり、これに対するアクションには余分なレイヤーが含まれることになります。
typeof new String(); // "object"
typeof ''; // "string"
これらは異なる型であるため、_JavaScript_インタプリタも異なる最適化を行うかもしれませんコメント。
宣言するとき。
var s = '0123456789';
と宣言すると、文字列プリミティブが生成されます。 その文字列プリミティブにはメソッドがあり、プリミティブをファーストクラスのオブジェクトに変換することなく、そのメソッドを呼び出すことができるようになっています。 ですから、文字列をオブジェクトに変換しなければならないから遅くなるのだというあなたの推測は正しくありません。 文字列はオブジェクトに変換される必要はありません。 プリミティブ自身がメソッドを呼び出すことができるのです。
それを本格的なオブジェクトに変換する(それによって新しいプロパティを追加することができます)ことは余分なステップであり、文字列の操作を速くするものではありません(実際、あなたのテストでは遅くなることが示されています)。
オブジェクトの存在は、ECMAScript/JavaScript エンジンの String の実際の動作にはほとんど関係ありません。ルートスコープには、単にこのための関数オブジェクトが含まれるだけだからです。つまり、文字列リテラルの場合は charAt(int) 関数が検索・実行されます。
実際のオブジェクトの場合は、さらにもう1つのレイヤーを追加して、charAt(int)メソッドもオブジェクト自体で検索してから標準の動作に入ります(上記と同じ)。どうやら、この場合の作業は意外と多いようです。
ところで、プリミティブが実際にオブジェクトに変換されるとは思いませんが、スクリプトエンジンは単にこの変数を文字列型としてマークし、そのために提供されるすべての関数を見つけることができるので、あたかもオブジェクトを呼び出したかのように見えます。これはスクリプトランタイムであり、OOランタイムとは異なる原則に基づいて動作することを忘れないでください。