この例で「use strict」がパフォーマンスを10倍向上させるのはなぜですか?


128

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

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行い、同じ違いが得られるかどうかを確認できますか?
Niet the Dark Absol 2016

1
this[i] === charはDOM環境でテストしましたが、結果は同じです
CristianTraìna16年

2
bergiの説明によると、count関数を呼び出すとき、thisパラメーターは文字列リテラルではなく文字列オブジェクトにキャストする必要がありますが、厳密モードでは正しく動作するためにパラメーターをキャストする必要はありません。なぜこれが当てはまらないのか、私は答えに非常に興味があります。
Nick Larsen

3
@NickLarsen:言語が仕様化された方法です。従来、JSはオブジェクトが常にであることを確認していましたthisが、厳密モードではそのステップをスキップするため、プリミティブ文字列、またはに提供されたものを取得しますthis

6
"use strict";男の子をどこにでも置く時間です!グーオールド
ジョナサン

回答:


155

厳密モードでは、thisコンテキストは強制的にオブジェクトになりません。非オブジェクトで関数を呼び出すと、thisその非オブジェクトになります。

対照的に、非厳密モードでは、thisまだオブジェクトでない場合、コンテキストは常に最初にオブジェクトにラップされます。たとえば、(42).toString()最初にオブジェクトをラップ42してから、そのオブジェクトをコンテキストとしてNumber呼び出します。strictモードでは、コンテキストが放置され、ちょうど呼び出すととしてコンテキスト。Number.prototype.toStringNumberthisthisNumber.prototype.toString42this

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

(function() {
  'use strict';
  console.log(typeof this);
}).call(42); // 'number'

あなたの場合、非ストリクトモードバージョンは、プリミティブstringStringオブジェクトラッパーにラップしたりアンラップしたりするのに多くの時間を費やします。一方、ストリクトモードバージョンは、プリミティブstringで直接動作するため、パフォーマンスが向上します。


1
また、の削除はwith、すべての変数ルックアップiircのビットにも役立ちます。
zzzzBov 2016

2
@zzzzBovが正しくありません。の削除は、ブラウザがどの変数式がどの変数を参照しているかwith推論できるため、非常に役立ちます。
John Dvorak

2
non-object thisはalways-objectよりも「厳密」であると私には直感的に思えませんthis
IllidanS4はモニカに2016

2
@ IllidanS4:これは主に、sloppyモードのグローバルオブジェクトであるthisis nullまたはの場合undefinedです。
Bergi

6
@ IllidanS4:必要に応じて、「実際のthis」対「ラッパーthis」と考えてください。オブジェクトラッパーは存在すべきではなかったものです。そのため、厳密モードでは、可能な場合はそれらをより回避するのが妥当です。
Ry-
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.