关于javascript:为什么“use strict”在这个例子中提高性能10倍?

Why “use strict” improves performance 10x in this example?

在扩展string.prototype性能这个问题之后,我真的很感兴趣,因为只需将"use strict"添加到String.prototype方法中,性能就提高了10倍。伯吉的解释很简短,没有向我解释。为什么两种几乎相同的方法之间会有如此大的差异,而顶部的"use strict"则不同?你能更详细地解释一下这背后的理论吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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');

结果:

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


在严格模式下,this上下文不强制为对象。如果在非对象上调用函数,那么this就是该非对象。

相反,在非严格模式下,如果this上下文已经不是对象,那么它总是首先被包装在对象中。例如,(42).toString()首先将42包装在Number对象中,然后调用Number.prototype.toStringNumber对象作为this上下文。在严格模式下,this上下文保持不变,只调用Number.prototype.toString42作为this上下文。

1
2
3
4
5
6
7
8
(function() {
  console.log(typeof this);
}).call(42); // 'object'

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

在您的例子中,非严格模式版本花费大量时间将原始的strings包装和解包到string对象包装器和背面。另一方面,严格模式版本直接作用于原始的string,提高了性能。