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[i] === char做一个测试,看看是否有同样的区别吗?
- 我在DOM环境中用this[i] === char进行了测试,结果是一样的。
- Bergi的解释说,当调用count函数时,必须将this参数强制转换为字符串对象,而不是字符串文本,而在严格模式下,不必为正确操作而强制转换。为什么这件事我无法理解,我对答案很感兴趣。
- @Nicklarsen:这只是语言的规范。传统上,JS会确保你总是有一个像this这样的对象,但是在严格的模式下,它跳过这一步,所以你得到了原始字符串,或者为this提供的任何东西。
- 是时候让所有的孩子们都去做了!gooold公司
- 你看过"使用严格"在JavaScript中的作用吗?"this"关键字是如何工作的??
- 还有stackoverflow.com/questions/13055/&hellip;
在严格模式下,this上下文不强制为对象。如果在非对象上调用函数,那么this就是该非对象。
相反,在非严格模式下,如果this上下文已经不是对象,那么它总是首先被包装在对象中。例如,(42).toString()首先将42包装在Number对象中,然后调用Number.prototype.toString,Number对象作为this上下文。在严格模式下,this上下文保持不变,只调用Number.prototype.toString和42作为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,提高了性能。
- 删除with对每个变量查找IIRC也有帮助。
- @ZZZZBOV不正确。删除EDOCX1[0]非常有帮助,因为它允许浏览器推断哪个变量表达式引用哪个变量。
- 理论上,this.length和this[i]也应该创建一个字符串外来对象(字符串原语没有属性),但浏览器可能不会这样做。
- 我用String对象进行了测试,每个函数的时间是相同的(考虑到实验误差后)。它们比非严格版本快6倍,比我系统中原始字符串的严格版本慢17倍。我还将var self = String(this);等添加到了非严格版本中,这实际上使速度提高到了与String对象的严格版本相同的速度,但原始字符串仍然慢了50%,可能是由于String的构造开销。
- 在我看来,不反对的this比总是反对的this更"严格",这是毫无道理的。
- @Illidans4:这主要是关于this是null或undefined的情况,这将是松散模式下的全局对象。
- @伊利丹4:如果你愿意,可以把它想象成"实际的this"和"包装的this"。对象包装器是一个本不应该存在的组合,因此严格模式在可能的情况下可以避免使用它们。
- 那么,如果我们与this合作,我们是否应该始终使用strict mode?
- @EdwardBlackStrict模式修复了JavaScript"旧"语义中的一些错误,通过将静默错误转化为实际错误来帮助您防止错误,并使浏览器能够更好地优化代码。如果您今天正在编写新的javascript代码,则应该始终使用严格模式。但是,启用严格模式可能会破坏旧代码,因此在将旧代码转换为现代JavaScript时要小心。
- strict mode是否总是提高性能?