Почему "использовать строгий" улучшает производительность 10x в этом примере?
Следуя вопросу Расширение производительности 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');
Ответы
Ответ 1
В строгом режиме контекст this
не является объектом. Если вы вызываете функцию на не-объект, this
будет просто это не объект.
Напротив, в нестрогом режиме контекст this
всегда сначала обернут в объект, если он еще не является объектом. Например, (42).toString()
сначала обертывает 42
в объекте Number
, а затем вызывает Number.prototype.toString
с объектом Number
как this
. В строгом режиме контекст this
остается нетронутым и просто вызывает Number.prototype.toString
с 42
как this
контекст.
(function() {
console.log(typeof this);
}).call(42); // 'object'
(function() {
'use strict';
console.log(typeof this);
}).call(42); // 'number'