2016-07-16 6 views
116

Extending String.prototype performanceの質問に続いて、"use strict"String.prototypeメソッドに追加するだけでパフォーマンスが10倍向上したので、私は本当に興味を持っています。 explanationbergiは短いので、私には説明しません。なぜ、2つのほとんど同じ方法の間にこのような劇的な違いがありますか?それは、"use strict"が一番上に違いがありますか?あなたはこれの背後にある理論とより詳細に説明できますか?この例では、「use strict」はパフォーマンスを10倍向上させる理由は何ですか?

String.prototype.count = function(char) { 
 
    var n = 0; 
 
    for (var i = 0; i < this.length; i++) 
 
    if (this[i] == char) n++; 
 
    return n; 
 
}; 
 

 
String.prototype.count_strict = function(char) { 
 
    "use strict"; 
 
    var n = 0; 
 
    for (var i = 0; i < this.length; i++) 
 
    if (this[i] == char) n++; 
 
    return n; 
 
}; 
 
// Here is how I measued speed, using Node.js 6.1.0 
 

 
var STR = '0110101110010110100111010011101010101111110001010110010101011101101010101010111111000'; 
 
var REP = 1e4; 
 

 
console.time('proto'); 
 
for (var i = 0; i < REP; i++) STR.count('1'); 
 
console.timeEnd('proto'); 
 

 
console.time('proto-strict'); 
 
for (var i = 0; i < REP; i++) STR.count_strict('1'); 
 
console.timeEnd('proto-strict');

結果:

proto: 101 ms 
proto-strict: 7.5 ms 
+1

'this [i] === char'でテストをして、同じ違いがあるかどうか確認できますか? –

+1

DOM環境で 'this [i] === char'を使ってテストした結果は同じです –

+2

bergiの説明によると、' count'関数を呼び出すと、 'this'パラメータは文字列にキャストされなければなりません厳密なモードでは正しく動作する必要はありませんが、文字列リテラルの代わりにオブジェクトを使用します。なぜこのケースが私を超えているのか、私はその答えに非常に興味があります。 –

答えて

148

In strict mode, the this context is not forced to be an object.あなたは非オブジェクトの関数を呼び出す場合は、thisだけでは非対象となります。

対照的に、非厳密モードでは、オブジェクトがまだオブジェクトでない場合、コンテキストは常に最初にオブジェクトにラップされます。例えば、(42).toString()は、最初にNumberオブジェクト内に42をラップし、次にNumberオブジェクトを持つNumber.prototype.toStringオブジェクトをthisコンテキストとして呼び出します。厳密なモードでは、thisのコンテキストは変更されず、そのままと42となり、コンテキストはthisとなります。あなたのケースでは

(function() { 
 
    console.log(typeof this); 
 
}).call(42); // 'object' 
 

 
(function() { 
 
    'use strict'; 
 
    console.log(typeof this); 
 
}).call(42); // 'number'
は、非strictモード版は、時間の折り返しと Stringオブジェクトラッパーと背中にプリミティブ string Sをアンラップの多くを費やしています。一方、strictモードのバージョンは、プリミティブ stringで直接動作し、パフォーマンスが向上します。

+1

また、 'with'を削除すると、すべての変数に少しでも役立ちますルックアップiirc。 – zzzzBov

+2

@zzzzBovが正しくありません。 'with 'を削除すると、どの変数の式がどの変数を参照しているのかをブラウザが推論できるようになります。 –

+0

理論的には、 'this.length'と' this [i] 'は文字列エキゾチックオブジェクトを作成する必要があります(文字列プリミティブはプロパティを持たない)が、おそらくブラウザはそれをしません。 – Oriol

関連する問題