webentwicklung-frage-antwort-db.com.de

Wie deklariert man private Variablen und private Methoden in der Klasse es6?

in es5 verwenden wir die Konstruktorfunktion  

function Person(name,gender){

    var initial ="";    // we use var key Word to make variable private

    function getNameWithInitial(){ // this is the private method to get name with initial
        console.log(this);
        initial = this.gender ==="male"?"Mr. ":"Mrs. ";
        return initial + this.name;
    }


    this.name = name;
    this.gender = gender;
    this.getName = function(){
        return getNameWithInitial.call(this);
    }


}


var manas = new Person("Manas","male");

console.log(manas.getName());

Meine Frage ist, wie man eine private Variable und eine private Methode in der Klasse es6 deklariert

14
manas

Eine Möglichkeit, dies zu erreichen, ist die Verwendung einer anderen ES2015 - Funktion, die als modules bekannt ist. 

Sie sind möglicherweise bereits mit AMD -Modulen oder commonJS -Modulen (die von Nodejs verwendet werden) vertraut. ES6/ES2015 enthält einen Standard für JS - wir nennen sie ES6-Module, aber sie sind jetzt Teil der JS-Sprache. Sobald Sie über Module verfügen, können Sie Informationen für private Funktionen und Objektvariablen ausblenden. Beachten Sie, dass nur das, was Sie "exportieren", für den Anrufcode des Clients sichtbar ist.

Lassen Sie uns Ihren Beispielcode durcharbeiten. Hier ist ein erster Schnitt:

person.js

 const getNameWithInitial = function () {
      let initial = this._gender === 'male' ?
      'Mr. ' :
      'Mrs. ';
      return initial + this._name;
    }

  export class Person {

    constructor(name, gender) {
        this._name = name;
        this._gender = gender;
      }

      get name() {
          return getNameWithInitial.call(this);
        }
    }
  }

client.js

import {Person} from './person';
const manas = new Person('Manas', 'male');
console.log(manas.name);  // this calls what was your getName function

Nun ist die Funktion getNameWithInitial praktisch privat, da sie nicht exportiert wird, sodass client.js sie nicht sehen kann.

Wir haben jedoch immer noch ein Problem für die Person-Klasse, da diese exportiert wird. Im Moment können Sie einfach zu Manas gehen und folgendes tun:

manas._name = 'Joe'

Mit Eigenschaften wie _name können wir Module und Symbole kombinieren . Dies ist eine leistungsstarke und dennoch leichte Methode zum Ausblenden von Informationen, die mit ES6 +/ES2015 verfügbar ist.

Symbol ist ein neuer eingebauter Typ. Jeder neue Symbolwert ist einzigartig. Daher kann als Schlüssel für ein Objekt verwendet werden.

Wenn der aufrufende Clientcode das für den Zugriff auf diesen Schlüssel verwendete Symbol nicht kennt, kann er den Code nicht abrufen, da das Symbol nicht exportiert wird.

Sehen wir uns unseren modifizierten Code an, um Symbole und Module zum Ausblenden von Klassenattributen zu verwenden.

person.js

const s_name = Symbol();
const s_gender = Symbol();

const getNameWithInitial = function () {
  let initial = this[s_gender] === 'male' ?
    'Mr. ' :
    'Mrs. ';
  return initial + this[s_name];
}

export class Person {

  constructor(name, gender) {
    this[s_name] = name;
    this[s_gender] = gender;
  }

  get name() {
    return getNameWithInitial.call(this);
  }
}

Ein Client kann also nicht einfach Folgendes tun:

 manas._name = 'Joe' 

weil _name nicht als Schlüssel für den Namenswert verwendet wird.

Symbole werden jedoch über Reflexionsfunktionen wie Object.getOwnPropertySymbols verfügbar gemacht. Beachten Sie, dass sie bei dieser Technik nicht "vollständig" privat sind.

import {Person} from './person';
const manas = new Person('Manas', 'male');
const vals = Object.getOwnPropertySymbols(manas);
manas[vals[0]] = 'Joanne';
manas[vals[1]] = 'female';

Nachricht zum Mitnehmen - Module sind im Allgemeinen eine gute Möglichkeit, etwas auszublenden. Wenn sie nicht exportiert werden und nicht für die Verwendung außerhalb des Moduls verfügbar sind und mit privat gespeicherten Symbolen als Schlüssel verwendet werden, können auch Klassenattribute ausgeblendet werden (jedoch nicht streng privat) ). Die Verwendung von Modulen ist heute mit Build-Tools verfügbar, z. webpack/browserify und babel.

18
arcseldon

Wenn Sie ein Analogon zur ES5-Lösung wünschen, ist das ganz einfach. Das constructor wird einfach zu dem, was die Schließung hält, und Sie fügen alle Methoden/Objekte hinzu, die sich an den privaten Zustand erinnern sollen.
Prototyp-Methoden haben keinen Zugriff auf die Schließung des ursprünglichen Konstruktors, ohne einige privilegierte Getter zu verwenden:

class Person {

  constructor ({ name, age, deepDarkSecret }) {
    const bribe = () => console.log(`Give me money, or everybody will know about ${ redactRandom(deepDarkSecret) }`);

    Object.assign(this, { name, age }); // assigning publicly accessible values
    Object.assign(this, { bribe }); // assign "privileged" methods (functions with closure-reference to initial values)
  }

  recallSecret () {
    console.log("I'm just a prototyped method, so I know nothing about any secret, unless I use a privileged function...");
    this.bribe();
  }
}

Wenn Sie sich die Netze anschauen, werden Sie feststellen, dass es nicht viel anders ist als in Ihrem Beispiel (verwenden Sie einfach "sauberere" Glocken und Pfeifen; vor allem beim Hinzufügen von Prototyp-/statischen Methoden). Es ist immer noch Prototyp darunter.

Wenn Sie den Luxus haben, ein beliebiges Modul/einen beliebigen Export zu verwenden (ES6 ist das Ideal), dann mit einem anderen Datentyp Sie können echte Privatsphäre haben und müssen nicht selbst bereinigen}.

Es sieht ein bisschen hässlich aus. Es wird wahrscheinlich weniger hässlich sein und hoffentlich die Grundlage für etwas saubereres in der Zukunft sein, aber wenn Sie instanzbasierten privaten Zugriff auch für prototypische Methoden wünschen, dann machen Sie one WeakMap, innerhalb des Moduls, aus dem Sie Ihre Klasse exportieren.

Verwenden Sie this als Schlüssel. __ Anstatt privilegierte Funktionen mit Schließzugriff zu erstellen, haben jetzt alle Prototypmethoden Schließzugriff auf die Schwachmaps ...
Der Nachteil ist, dass Sie immer, wenn Sie private Variablen wünschen, diese in WeakMap nachschlagen müssen, anstatt sie aus/aus this herauszuziehen.

const personalBaggage = new WeakMap();

class Person {
  constructor ({ name, age, darkestMoment }) {
    const privates = { name, age, darkestMoment };
    personalBaggage.add(this, privates);
  }

  recallDarkestHour () {
    const { darkestMoment } = personalBaggage.get(this);
    console.log(darkestMoment);
  }
}

export default Person;

Solange Sie die Referenz in this nicht verlieren, sollte dies einfach funktionieren.
Anders als bei Verwendung von Symbol können Sie keinen Verweis auf das private Objekt erhalten, egal wie sehr Sie es versuchen.
Wenn Sie die Symbole auf dem Objekt kennen, können Sie die Eigenschaften anhand der Symbole nachschlagen.
.__ Die Liste der Symbole für jedes Objekt zu erhalten, ist nur ein FunktionsaufrufSymbol geht es nicht darum, die Dinge geheim zu halten; Es geht darum, Dinge vor Kollisionen zu schützen und gemeinsame Symbole zu definieren, die für jedes Objekt/jede Funktion verwendet werden können, aber nicht in Schleifen aufgenommen werden, nicht versehentlich aufgerufen oder überschrieben werden, und so weiter.

Wenn Sie den privaten Datenbestand in einer Weakmap mit this als Schlüssel speichern, haben Sie Zugriff auf ein vollständig verstecktes Dataset, auf das außerhalb dieses Moduls vollständig zugegriffen werden kann.
Was besser ist, der Schlüssel/Wert in Schwachmaps hindert den GC nicht daran, sie aufzuräumen.
Normalerweise würden sie dort bleiben, wenn sie in einer Reihe stehen würden. Wenn der letzte Platz, an dem ein Objekt verwendet wird, als Schlüssel in einer Weakmap dient, wird es gesammelt und der Weakmap-Wert wird automatisch gelöscht (im nativen ES6 können die Speicherboni nicht gefüllt werden, das Objekt jedoch).

5
Norguard

hier ist ein wirklich guter Beitrag zu diesem Thema. Ich wusste nicht viel darüber in ES6 vor Ihrer Frage, aber nach der Überprüfung sieht es wirklich cool aus. Sie erstellen also ein Symbol, das der Funktion zugeordnet ist. 

hier ist der Code direkt von ihrem Sitz.

var Person = (function() {
    var nameSymbol = Symbol('name');

    function Person(name) {
        this[nameSymbol] = name;
    }

    Person.prototype.getName = function() {
        return this[nameSymbol];
    };

    return Person;
}());

var p = new Person('John');

Private Immobilien in JavaScript

0
andre mcgruder

Sie können dies mit Symbol erreichen.

const _name = Symbol();

class Person {
  constructor(name) {
    this[_name] = name;
  } 
}

const person = new Person('John');

alert(person.name);
// => undefined

0
jlowgren