为什么在此示例中,“使用严格”可将性能提高 10 倍?

2022-08-30 04:32:54

在扩展String.prototype性能的问题之后,我真的很感兴趣,因为仅仅添加一种方法就可以将性能提高10倍。bergi的解释很短,没有向我解释。为什么两种几乎相同的方法之间存在如此巨大的差异,而这些方法仅在顶部有所不同?您能更详细地解释一下这背后的理论吗?"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

相反,在非严格模式下,如果上下文还不是对象,则始终首先将其包装在对象中。例如,首先包装一个对象,然后以该对象作为上下文进行调用。在严格模式下,上下文保持不变,只是调用作为上下文。this(42).toString()42NumberNumber.prototype.toStringNumberthisthisNumber.prototype.toString42this

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

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

在你的例子中,非严格模式版本花费了大量时间将原语包装和解开包装到对象包装器中并返回。另一方面,严格模式版本直接在基元上工作,这提高了性能。stringStringstring


答案 2