564 Stimmen

Private Eigenschaften in JavaScript ES6 Klassen

Ist es möglich, private Eigenschaften in ES6-Klassen zu erstellen?

Hier ist ein Beispiel. Wie kann ich den Zugriff auf instance.property verhindern?

class Something {
  constructor(){
    this.property = "test";
  }
}

var instance = new Something();
console.log(instance.property); //=> "test"

1voto

StepUp Punkte 29996

Es ist möglich, private Methoden in Klassen mit WeakMap zu haben.

Laut MDN Web Docs:

Das WeakMap-Objekt ist eine Sammlung von Schlüssel/Wert-Paaren, bei der die Schlüssel nur Objekte sind und die Werte beliebige Werte sein können.

Die Objektreferenzen in den Schlüsseln werden schwach gehalten, was bedeutet, dass sie ein Ziel für die Garbage Collection (GC) sind, wenn keine andere Referenz zum Objekt mehr vorhanden ist.

Und dies ist ein Beispiel dafür, wie eine Queue-Datenstruktur mit einem privaten Member _items erstellt wird, der ein Array enthält.

const _items = new WeakMap();

class Queue {    
    constructor() {
        _items.set(this, []);
    }

    enqueue( item) {
        _items.get(this).push(item);
    }    

    get count() {
        return _items.get(this).length;        
    }

    peek() {
        const anArray = _items.get(this);
        if( anArray.length == 0)
            throw new Error('There are no items in array!');

        if( anArray.length > 0)
            return anArray[0];
    }

    dequeue() {        
        const anArray = _items.get(this);
        if( anArray.length == 0)
            throw new Error('There are no items in array!');

        if( anArray.length > 0)
            return anArray.splice(0, 1)[0];
    }    
}

Ein Beispiel für die Verwendung:

const c = new Queue();
c.enqueue("eins");
c.enqueue("zwei");
c.enqueue("drei");
c.enqueue("vier");
c.enqueue("fünf");
console.log(c);

Der private Member _items ist versteckt und kann in den Eigenschaften oder Methoden eines Queue-Objekts nicht gesehen werden:

Eingabe-Bildbeschreibung hier

Der private Member _items im Queue-Objekt kann jedoch auf folgende Weise erreicht werden:

const anArray = _items.get(this);

1voto

Hier ist die myThing Variable privat und Teil des Closure:

class Person {
  constructor() {

    var myThing = "Hallo Welt";

    return {
      thing: myThing,
      sayThing: this.sayThing
    }
  }

  sayThing() {
    console.log(this.thing);
  }
}

var person = new Person();

console.log(person);

0voto

Jesse Fender Punkte 321

Ich habe einen Workaround, der wunderbar funktioniert und ziemlich einfach ist... obwohl die Leistung wahrscheinlich nicht die beste ist... aber es funktioniert und funktioniert gut.

Der Trick besteht darin, dass bis private Eigenschaften und Funktionen festgelegt und standardisiert/angenommen sind, Workarounds erforderlich sind und dies ein weiterer Workaround ist...

class ClassPrivateProperties {
    constructor(instance) {
        const $this = instance;
        let properties = {};
        this.prop = (key, value = undefined) => {
            if (!value) {
                return properties[key];
            } else {
                properties[key] = value;
            }
        };
        this.clear = instance => {
            if ($this === instance) {
                properties = {};
                return true;
            } else {
                return false;
            }
        }
    }
}

Dies ist eine Beispielnutzung, die beliebig sein kann (auch wenn Sie den obigen verwenden, können Sie ihn gerne verbessern)

class Test {
    constructor() {
        this._privateProps = new ClassPrivateProperties(this);
    }
    property(key, value = undefined) {
        if (!value) {
            return this._privateProps.prop(key);
        } else {
            this._privateProps.prop(key, value);
        }
    }
    clear() { return this._privateProps.clear(this); }
}
const test = new test;
test.property('myKey','some value here');
console.log(test.property('myKey'));

Wie bereits erwähnt, ist dies wahrscheinlich nicht das Beste vom Besten, aber es funktioniert und macht die Eigenschaften wirklich privat.

0voto

hmmhmmhm Punkte 31

Ich habe ein Modul entwickelt, das Ihnen hilft, die Zugriffsbeschränkung in der JavaScript-Klasse namens Capsulable zu verwenden. (Privat & Geschützt Statisch)

Wenn Sie interessiert sind, schauen Sie sich mein Paket unten an. https://github.com/hmmhmmhm/capsulable

const Capsulable = require('capsulable')
const Field = Capsulable()

class A {
    constructor(_field){
        // Konfigurieren der Datenfelder.
        Field(this, _field)

        // Der folgende Code ermöglicht den Zugriff auf
        // die Datenfelder beim Erstellen von
        // Funktionen innerhalb der Klasse.
        Field(this).private
        Field(this).protected
        Field(this).protectedStatic
    }
}

module.exports = A

0voto

user260778 Punkte 101

Wir können eine private Eigenschaft einer Klasse mit Getter und Setter emulieren.

Bsp. 1

class FootballClub {
    constructor (cname, cstadium, ccurrentmanager) {
        this.name = cname;
        this._stadium  = cstadium;  //  wir behandeln diese Eigenschaft als privat und geben ihr Getter und Setter.
        this.currmanager = ccurrentmanager;
    }

    get stadium( ) {
        return this._stadium.toUpperCase();
    }

}

let club = new FootballClub("Arsenal", "Emirates" , "Arteta")
console.log(club);
//FootballClub {
//    name: 'Arsenal',
//    _stadium: 'Emirates',
//    currmanager: 'Arteta'
//  }
console.log( club.stadium ); // EMIRATES
club.stadium = "Highbury"; // TypeError: Kann die Eigenschaft Stadion von # nicht setzen, die nur einen Getter hat

In dem obigen Beispiel haben wir keine Setter-Methode für stadium angegeben und daher können wir keinen neuen Wert dafür setzen. Im nächsten Beispiel wird ein Setter für stadium hinzugefügt.

Bsp. 2

class FootballClub {
    constructor (cname, cstadium, ccurrentmanager) {
        this.name = cname;
        this._stadium  = cstadium;  //  wir behandeln diese Eigenschaft als privat und geben ihr Getter und Setter.
        this.currmanager = ccurrentmanager;
    }

    get stadium( ) {
        return this._stadium.toUpperCase();
    }

    set stadium(val) {
       this._stadium = val;
    }
}

let club = new FootballClub("Arsenal", "Emirates" , "Arteta")
console.log(club.stadium); // EMIRATES
club.stadium = "Emirates Stadium";
console.log(club.stadium); // EMIRATES STADIUM

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X