Maison >interface Web >js tutoriel >Résumé de l'implémentation des variables privées dans ES6 (exemple de code)

Résumé de l'implémentation des variables privées dans ES6 (exemple de code)

不言
不言avant
2018-11-21 11:25:491686parcourir

Cet article vous apporte un résumé de l'implémentation des variables privées dans ES6 (exemples de code). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

En lisant "Introduction à ECMAScript 6", j'ai vu des implémentations dispersées de variables privées, je vais donc les résumer ici.

1. Accord

mise en œuvre

class Example {
    constructor() {
        this._private = 'private';
    }
    getName() {
        return this._private
    }
}

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex._private); // private

Avantages

  1. Méthode d'écriture simple

  2. Facile à déboguer

  3. Bonne compatibilité

Inconvénients

  1. Les externes peuvent accéder et modifier

  2. Le langage n'a pas de mécanisme de correspondance. Par exemple, l'instruction for in énumérera tous les attributs

  3. Conflit de noms

2. Clôture

Mise en œuvre 1

/**
 * 实现一
 */
class Example {
  constructor() {
    var _private = '';
    _private = 'private';
    this.getName = function() {return _private}
  }
}

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex._private); // undefined

Avantages

  1. Aucun conflit de noms

  2. Les externes ne peuvent pas accéder et modifier

Inconvénients

  1. La logique du constructeur devient compliquée. Le constructeur ne doit effectuer que l'initialisation des objets. Désormais, pour implémenter des variables privées, il doit inclure l'implémentation de certaines méthodes, et l'organisation du code est légèrement floue.

  2. Les méthodes existent sur les instances, pas sur les prototypes, et les sous-classes ne peuvent pas utiliser super pour appeler

  3. La construction ajoute un peu de surcharge

Mise en œuvre 2

/**
 * 实现二
 */
const Example = (function() {
  var _private = '';

  class Example {
    constructor() {
      _private = 'private';
    }
    getName() {
      return _private;
    }
  }

  return Example;

})();

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex._private); // undefined

Avantages

  1. Aucun conflit de nom

  2. Non accessible de l'extérieur Et modifications

Inconvénients

  1. La méthode d'écriture est un peu compliquée

  2. La construction ajoute un peu frais généraux

3. Implémentation du symbole

const Example = (function() {
    var _private = Symbol('private');

    class Example {
        constructor() {
          this[_private] = 'private';
        }
        getName() {
          return this[_private];
        }
    }

    return Example;
})();

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex.name); // undefined

Avantages

  1. Aucun conflit de nom

  2. Impossible d'accéder et de modifier en externe

  3. Aucune perte de performances

Inconvénients

  1. La méthode d'écriture est légèrement compliquée

  2. La compatibilité est également bonne

4. WeakMap

mise en œuvre

/**
 * 实现一
 */
const _private = new WeakMap();

class Example {
  constructor() {
    _private.set(this, 'private');
  }
  getName() {
      return _private.get(this);
  }
}

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex.name); // undefined

Si vous l'écrivez comme ceci, vous pourriez avoir l'impression que l'encapsulation n'est pas suffisante. Vous pouvez également l'écrire comme ceci :

/**
 * 实现二
 */
const Example = (function() {
  var _private = new WeakMap(); // 私有成员存储容器

  class Example {
    constructor() {
      _private.set(this, 'private');
    }
    getName() {
        return _private.get(this);
    }
  }

  return Example;
})();

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex.name); // undefined

Avantages

  1. Aucun conflit de nom

  2. Impossible d'accéder et de modifier en externe

Inconvénients

  1. L'écriture est plus gênante

  2. La compatibilité est un peu problématique

  3. Il y a un certain coût de performance

5. La dernière proposition

class Point {
  #x;
  #y;

  constructor(x, y) {
    this.#x = x;
    this.#y = y;
  }

  equals(point) {
    return this.#x === point.#x && this.#y === point.#y;
  }
}
Alors pourquoi ne pas utiliser directement les champs privés ? Par exemple :

class Foo {
  private value;

  equals(foo) {
    return this.value === foo.value;
  }
}
Pour faire simple, c'est gênant, et bien sûr il y a des considérations de performances...

Par exemple, si nous n'utilisons pas #, mais utilisons private Mots-clés :

class Foo {
  private value = '1';

  equals(foo) {
    return this.value === foo.value;
  }
}

var foo1 = new Foo();
var foo2 = new Foo();

console.log(foo1.equals(foo2));
Ici, nous créons deux nouvelles instances, puis passons foo2 comme paramètre dans la méthode d'instance de foo1.

Alors pouvons-nous obtenir la valeur de foo2.value ? Si nous

directement, nous ne pourrons certainement pas obtenir la valeur. Après tout, c'est une variable privée, mais equals est une méthode de classe de Foo, alors pouvons-nous l'obtenir ? foo2.value

La réponse est oui.

En fait, c'est la même chose dans d'autres langages, comme Java et C++

Les fonctions membres d'une classe peuvent accéder aux variables privées des instances du même type C'est parce que la confidentialité l'est. pour l'implémentation, les informations "externes" sont cachées dans la classe elle-même. Il n'est pas nécessaire d'interdire l'accès aux variables privées. Vous pouvez également comprendre que les restrictions sur les variables privées sont basées sur la classe et non sur l'objet. offrir aux utilisateurs la commodité d’apporter.

Puisque l'obtention de la valeur est correcte, le résultat imprimé devrait être vrai, mais que se passe-t-il si la valeur que nous transmettons n'est pas une instance de Foo, mais un autre objet ?

var foo1 = new Foo();

console.log(foo1.equals({
  value: 2
}));
Bien sûr, le code ici peut s'exécuter normalement, mais pour le compilateur, c'est un peu gênant, car le compilateur ne sait pas si la valeur est un attribut normal ou un attribut privé de foo, donc le compilateur Vous devez porter un jugement, juger d'abord si foo est une instance de Foo, puis obtenir la valeur.

Cela signifie également qu'un tel jugement doit être fait pour chaque accès aux attributs, et le moteur a été hautement optimisé autour de l'accès aux attributs et est trop paresseux pour changer, et cela réduit également la vitesse.

Mais en plus de ce travail, il y a d'autres choses à considérer, telles que :

  1. Vous devez encoder la clé privée dans chaque environnement lexical

  2. Peut-on traverser ces propriétés ?

  3. Lorsque les attributs privés et les attributs normaux portent le même nom, qui bloquera qui ?

  4. Comment empêcher la détection des noms d'attributs privés.

Pour plus de discussions sur l'utilisation de # au lieu de privé, veuillez vous référer à ce numéro.

Bien sûr, ces problèmes peuvent être résolus, mais ils sont un peu gênants.

Et si vous choisissez #, la méthode d'implémentation n'aura rien à voir avec les propriétés des objets JavaScript. Elle utilisera la méthode

et une nouvelle syntaxe de recherche de slot. Bref, elle sera plus simple que la méthode privée. méthode de mise en œuvre. private slots

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer