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


128

我真的很感兴趣,因为扩展了String.prototype性能这个问题,因为仅添加"use strict"一种String.prototype方法就可以将性能提高10倍。该解释BERGI是短暂的,并没有向我解释。为什么两种几乎完全相同的方法之间有如此巨大的差异,只是"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

1
this[i] === char在DOM环境中进行了测试,结果是一样的
CristianTraìna16年

2
bergi的解释说,当您调用该count函数时,必须将this参数强制转换为字符串对象而不是字符串文字,而在严格模式下则不必强制参数才能正确操作。为什么是这种情况超出了我,我对答案非常感兴趣。
尼克·拉尔森

3
@NickLarsen:这就是语言的指定方式。传统上,JS将确保您始终有一个对象this,但是在严格模式下,它会跳过该步骤,因此您将获得原始字符串或提供的任何内容this

6
现在是时候"use strict";到处放男孩了!Goooold
Jonathan

Answers:


155

在严格模式下,this不会强制上下文成为对象。如果您在一个非对象上调用一个函数,this则将只是该非对象。

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

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

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

在您的情况下,非严格模式版本会花费大量时间将原始strings 包装和解包到String对象包装器中并返回。另一方面,严格模式版本可直接在原始类型上使用string,从而提高了性能。


1
并且with对于每个变量查找iirc 的删除也有所帮助。
zzzzBov

2
@zzzzBov不正确。删除with帮助极大,因为它允许浏览器推断哪个变量表达式引用哪个变量。
约翰·德沃夏克

2
对我来说,似乎非直觉的对象this比“总是” 的对象“更严格” this
IllidanS4希望莫妮卡回到

2
@ IllidanS4:这主要是关于thisis null或的情况undefined,这是草率模式下的全局对象。
Bergi

6
@ IllidanS4:如果愿意,可以将其视为“实际this”与“包装器this”。对象包装程序是不应该存在的,因此严格模式将尽可能避免它们。
Ry-
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.