J'ai récemment développé Angular Cloud Data Connector, qui permet aux développeurs Angular d'utiliser des données cloud, en particulier Azure Mobile Services, à l'aide de normes Web telles que la base de données indexée. J'essayais de créer un moyen pour les développeurs JavaScript d'intégrer des membres privés à un objet.
Ma technique pour ce cas particulier consiste à utiliser ce que j'appelle «espace de fermeture». Dans ce tutoriel, je souhaite partager avec vous la manière de l'utiliser pour vos propres projets et en quoi cela affecte les performances et la mémoire des principaux navigateurs..
Mais avant de plonger dans le sujet, laissez-moi vous expliquer pourquoi vous avez peut-être besoin de membres privés, ainsi que d'une autre manière de «simuler» des membres privés..
N'hésitez pas à me contacter sur Twitter si vous souhaitez discuter de cet article: @deltakosh.
Lorsque vous créez un objet à l'aide de JavaScript, vous pouvez définir des membres de valeur. Si vous souhaitez contrôler l'accès en lecture / écriture sur ceux-ci, vous avez besoin d'accesseurs pouvant être définis comme suit:
var entity = ; entity._property = "bonjour le monde"; Object.defineProperty (entity, "property", get: function () return this._property;, set: function (value) this._property = value;, enumerable: true, configurable: true);
En faisant cela, vous avez un contrôle total sur les opérations de lecture et d’écriture. Le problème est que le _propriété
le membre est toujours accessible et peut être modifié directement.
C’est exactement pourquoi vous avez besoin d’un moyen plus robuste de définir des membres privés accessibles uniquement aux fonctions d’objet..
La solution consiste à utiliser un espace de fermeture. Le navigateur crée cet espace mémoire chaque fois qu’une fonction interne a accès aux variables de la portée d’une fonction externe. Cela peut parfois être délicat, mais pour notre sujet, c'est une solution parfaite.
Modifions donc le code précédent pour utiliser cette fonctionnalité:
var createProperty = function (obj, prop, currentValue) Object.defineProperty (obj, prop, get: function () return currentValue;, set: function (valeur) currentValue = valeur;, enumérable: true, configurable : vrai ); var entity = ; var myVar = "hello world"; createProperty (entité, "propriété", myVar);
Dans cet exemple, le createProperty
la fonction a valeur actuelle
variable que les fonctions get et set peuvent voir. Cette variable va être sauvegardée dans l'espace de fermeture des fonctions get et set. Seules ces deux fonctions peuvent maintenant voir et mettre à jour le valeur actuelle
variable! Mission accomplie!
Le seul inconvénient que nous avons ici est que la valeur source (maVar
) est toujours accessible. Voici donc une autre version pour une protection encore plus robuste:
var createProperty = fonction (obj, prop) var currentValue = obj [prop]; Object.defineProperty (obj, prop, get: function () return currentValue;, set: function (valeur) currentValue = value;, enumerable: true, configurable: true); var entity = propriété: "bonjour le monde"; createProperty (entité, "propriété");
En utilisant cette méthode, même la valeur source est détruite. Donc mission accomplie!
Voyons maintenant la performance.
De toute évidence, les espaces de fermeture ou même les propriétés sont plus lents et plus coûteux qu'une simple variable. C'est pourquoi cet article se concentre davantage sur la différence entre la technique habituelle et la technique de l'espace de fermeture..
Pour confirmer que l’approche d’espace de fermeture n’est pas trop chère par rapport à la méthode standard, j’ai écrit ce petit repère:
L'informatique…
Je crée 1 million d'objets, tous avec un membre de la propriété. Ensuite, je fais trois tests:
Voici un tableau et un graphique des résultats:
Nous pouvons voir que la version de l'espace de fermeture est toujours plus rapide que la version normale et en fonction du navigateur, cela peut être une optimisation vraiment impressionnante.
Les performances de Chrome sont inférieures à mes attentes. Il y a peut-être un bug, alors pour être sûr, j'ai contacté l'équipe de Google pour savoir ce qui se passe ici. De plus, si vous souhaitez tester le fonctionnement de ce nouveau navigateur Microsoft Edge-Microsoft, qui sera livré par défaut avec Windows 10, vous pouvez le télécharger ici..
Cependant, si nous regardons de plus près, nous pouvons constater que l'utilisation d'un espace de fermeture ou même d'une propriété peut être dix fois plus lente que l'accès direct à un membre. Alors soyez averti et utilisez-le à bon escient.
Nous devons également vérifier que cette technique ne consomme pas trop de mémoire. Pour évaluer la mémoire, j'ai écrit ces trois petits morceaux de code:
var sampleSize = 1000000; var entités = []; // Création d'entités pour (var index = 0; index < sampleSize; index++) entities.push( property: "hello world (" + index + ")" );
var sampleSize = 1000000; var entités = []; // Ajout d'une propriété et utilisation d'un membre local pour enregistrer une valeur privée pour (var index = 0; index < sampleSize; index++) var entity = ; entity._property = "hello world (" + index + ")"; Object.defineProperty(entity, "property", get: function () return this._property; , set: function (value) this._property = value; , enumerable: true, configurable: true ); entities.push(entity);
var sampleSize = 1000000; var entités = []; var createProperty = function (obj, prop, currentValue) Object.defineProperty (obj, prop, get: function () return currentValue;, set: function (valeur) currentValue = valeur;, enumérable: true, configurable : vrai ); // Ajout d'une propriété et utilisation de l'espace de fermeture pour enregistrer une valeur privée pour (var index = 0; index < sampleSize; index++) var entity = ; var currentValue = "hello world (" + index + ")"; createProperty(entity, "property", currentValue); entities.push(entity);
Ensuite, j'ai exécuté ces trois codes et lancé le profileur de mémoire intégré (exemple ici avec les outils F12):
Voici les résultats que j'ai obtenus sur mon ordinateur:
Entre espace de fermeture et mode normal, seul Chrome a des résultats légèrement supérieurs pour la version avec espace de fermeture. IE11 et Firefox utilisent un peu plus de mémoire, mais les navigateurs sont relativement comparables. Les utilisateurs ne remarqueront probablement pas de différence entre les navigateurs modernes..
Cela vous surprendra peut-être un peu, mais Microsoft a beaucoup à apprendre gratuitement sur de nombreux sujets JavaScript open source et nous avons pour mission de créer beaucoup plus avec Microsoft Edge. Découvrez moi-même:
Ou la série d'apprentissage de notre équipe:
Et quelques outils gratuits: Communauté Visual Studio, Azure Trial et outils de test multi-navigateurs pour Mac, Linux ou Windows..
Comme vous pouvez le constater, les propriétés d’espace de fermeture peuvent être une excellent moyen de créer des données vraiment privées. Vous devrez peut-être faire face à une légère augmentation de la consommation de mémoire, mais de mon point de vue, cela reste assez raisonnable (et à ce prix, vous pourrez améliorer considérablement vos performances par rapport à l'utilisation habituelle)..
Et au fait, si vous voulez l'essayer vous-même, veuillez trouver tout le code utilisé ici. Il existe un bon "guide" sur les services Azure Mobile ici..
Cet article fait partie de la série Web de développement Web de Microsoft. Nous sommes ravis de partager Microsoft Edge et le nouveau Moteur de rendu EdgeHTML avec toi. Obtenez des machines virtuelles gratuites ou testez à distance sur votre appareil Mac, iOS, Android ou Windows @ http://dev.modern.ie/.
Apprendre JavaScript: le guide complet
Nous avons créé un guide complet pour vous aider à apprendre le JavaScript, que vous soyez débutant en tant que développeur Web ou que vous souhaitiez explorer des sujets plus avancés..