web-dev-qa-db-fra.com

Pourquoi "utiliser strictement" améliore les performances 10x dans cet exemple?

Suite à la question Extension des performances de String.prototype Je suis vraiment intrigué, car simplement ajouter "use strict" à un String.prototype la méthode a amélioré les performances 10 fois. Le explication par bergi est court et ne me l'explique pas. Pourquoi il y a une telle différence entre deux méthodes presque identiques, qui ne diffèrent que par "use strict" au sommet? Pouvez-vous expliquer plus en détail et avec la théorie derrière cela?

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');

Résultat:

proto: 101 ms
proto-strict: 7.5 ms
125
exebook

En mode strict, le contexte this n'est pas forcé d'être un objet. Si vous appelez une fonction sur un non-objet, this sera simplement ce non objet.

En revanche, en mode non strict, le contexte this est toujours d'abord enveloppé dans un objet s'il ne l'est pas déjà. Par exemple, (42).toString() premiers tours 42 dans un objet Number, puis appelle Number.prototype.toString avec l'objet Number comme contexte this. En mode strict, le contexte this n'est pas modifié et appelle simplement Number.prototype.toString avec 42 comme this contexte.

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

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

Dans votre cas, la version en mode non strict passe beaucoup de temps à encapsuler et à décompresser les primitifs strings en String encapsuleurs d'objet et inversement. Par contre, la version en mode strict fonctionne directement sur la primitive string, ce qui améliore les performances.

154
Mattias Buelens