JavaScript 1.8.5 (ECMAScript 5) ajoute quelques méthodes intéressantes qui empêchent de futures modifications d'un objet passé, avec différents degrés de minutie:
On peut supposer que le point principal de ces erreurs est de détecter les erreurs: si vous savez que vous ne voulez pas modifier un objet après un certain point, vous pouvez le verrouiller afin qu'une erreur soit levée si vous essayez par inadvertance de le modifier plus tard. (Pourvu que vous ayez fait "use strict";
C'est.)
Ma question: dans les moteurs JS modernes tels que V8, y a-t-il un avantage en termes de performances (par exemple, des recherches de propriétés plus rapides, une empreinte mémoire réduite) dans le verrouillage objets en utilisant les méthodes ci-dessus?
(Voir aussi Belle explication de John Resig - ne mentionne pas les performances, cependant.)
Il n'y a eu aucune différence dans les performances depuis au moins Chrome 47.0.2526.80 (64 bits).
Testing in Chrome 6.0.3359 on Mac OS 10.13.4
-----------------------------------------------
Test Ops/sec
non-frozen object 106,825,468 ±1.08% fastest
frozen object 106,176,323 ±1.04% fastest
Test de performance (disponible sur http://jsperf.com/performance-frozen-object ):
const o1 = {a: 1};
const o2 = {a: 1};
Object.freeze(o2);
// Non-frozen object:
for(var key in o1);
// Frozen object:
for(var key in o2);
Mise à jour 03.05.2018 : Il n'y a pas de différence de performances sur Chrome 66.0. 3359 (64 bits)
Mise à jour 06.03.2017 : Il n'y a aucune différence de performances sur Chrome 56.0. 2924 (64 bits)
Mise à jour 13.12.2015 : il n'y a pas de différence de performances sur Chrome 47.0. 2526.80 (64 bits)
Avec Chrome 34, un objet gelé fonctionne légèrement mieux qu'un objet non gelé dans le cas de test de @ pimvdb (résultats ci-dessous). La différence, cependant, ne semble pas être assez grande pour justifier l'utilisation cette technique pour des avantages de performance.
http://jsperf.com/performance-frozen-object
Testing in Chrome 34.0.1847.116 on OS X 10.9.2
----------------------------------------------
Test Ops/sec
non-frozen object 105,250,353 ±0.41% 3% slower
frozen object 108,188,527 ±0.55% fastest
L'exécution des cas de test de @ kangax montre que les deux versions de l'objet fonctionnent à peu près de la même manière:
http://jsperf.com/performance-frozen-object-prop-access
Testing in Chrome 34.0.1847.116 on OS X 10.9.2
----------------------------------------------
Test Ops/sec
non-frozen object 832,133,923 ±0.26% fastest
frozen object 832,501,726 ±0.28% fastest
http://jsperf.com/http-jsperf-com-performance-frozen-object-instanceof
Testing in Chrome 34.0.1847.116 on OS X 10.9.2
----------------------------------------------
Test Ops/sec
non-frozen object 378,464,917 ±0.42% fastest
frozen object 378,705,082 ±0.24% fastest
Dans Google Chrome (donc V8, c'est-à-dire), un objet figé itère 98% plus lentement qu'un objet normal.
http://jsperf.com/performance-frozen-object
Test name* ops/sec
non-frozen object 32,193,471
frozen object 592,726
C'est probablement parce que ces fonctions sont relativement nouvelles et probablement pas encore optimisées (mais c'est juste ma supposition, je ne connais honnêtement pas la raison).
Quoi qu'il en soit, je ne recommande vraiment pas de l'utiliser pour des performances optimales, car cela n'a apparemment aucun sens.
* Le code du test est:
var o1 = {a: 1};
var o2 = {a: 1};
Object.freeze(o2);
Test 1 (objet non figé):
for(var key in o1);
Test 2 (objet gelé):
for(var key in o2);
Depuis que cette réponse a été écrite à l'origine, le bogue dans V8 qui a causé ce problème a été corrigé. Voir la réponse de Jan Molak ci-dessus pour mor
En théorie, le gel d'un objet vous permet de donner des garanties plus solides sur la forme d'un objet.
Cela signifie que le VM peut compacter la taille de la mémoire.
Cela signifie que le VM peut optimiser les recherches de propriétés dans la chaîne de prototypes.
Cela signifie que toutes les références actives sont devenues non vivantes car l'objet ne peut plus changer.
En pratique, les moteurs JavaScript ne font pas encore ces optimisations agressives.
V8 a optimisé Object.freeze à partir du 20 juin 2013. Et Object.seal et Object.preventExtensions à partir du 10 décembre 2014. Voir le problème https://code.google.com/p/chromium/issues/ détail? id = 11596
Selon le problème du code Google :
La différence de performances est due à la structure de données du magasin de sauvegarde. Pour quelques propriétés, le descripteur d'objet décrit où les propriétés sont stockées, dans un tableau de propriétés. Si le nombre de propriétés augmente, nous finissons par passer à un dictionnaire pour le magasin de sauvegarde, qui est moins performant, mais plus flexible. Lorsque nous figons un objet, ce qui se fait, c'est que toutes les propriétés sont définies sur non configurables et non inscriptibles. Le stockage de ces attributs n'est possible que dans un magasin de sauvegarde de dictionnaire, nous passons donc à cela.
EDIT: Plus de travail a été fait pour l'optimiser et la différence entre les objets normaux et les objets figés a été réduite à environ 20%. Les objets scellés mettent encore deux fois plus de temps à se répéter, mais des travaux sont en cours.
Si vous êtes intéressé par les performances de l'objet creation (littéral vs figé vs scellé vs Immutable.Map
), j'ai créé un test sur jsPerf pour vérifier cela.
Jusqu'à présent, je n'ai eu l'occasion de le tester qu'en Chrome 41 et Firefox 37. Dans les deux navigateurs, la création d'un objet figé ou scellé prend environ trois fois plus que la création d'un littéral - alors que le Immutable.Map
fonctionne environ 50 fois moins bien que le littéral.
La seule raison pour laquelle je vois ces méthodes dans le code de production est que vous pouvez avoir des objets scellés ou gelés, à des fins d'intégrité.
Par exemple, j'écris une petite bibliothèque, qui fonctionne très bien et vous propose un ensemble de méthodes dans un objet, mais je ne veux pas que vous changiez ou n'écrasiez aucune de mes propriétés ou méthodes. Je ne dis pas que je peux vous empêcher de le faire, mais je peux essayer de vous empêcher de le faire par accident, ce qui est peut-être plus important.
De plus, ces méthodes sont faciles à "caler" dans un environnement qui ne les connaît pas, en renvoyant simplement l'objet d'origine. Bien sûr, cela n'aurait alors aucun effet.
Je ne vois aucune raison liée aux performances de le faire.