Frage

Nun habe ich versucht, in irgendeiner Art und Weise dies möglich herauszufinden. Hier ist der Code:

a=function(text)
{
   var b=text;
   if (!arguments.callee.prototype.get)
      arguments.callee.prototype.get=function()
    {
         return b;
    }
    else
      alert('already created!');
}

var c=new a("test");  // creates prototype instance of getter
var d=new a("ojoj");  // alerts already created
alert(c.get())        // alerts test 
alert(d.get())        // alerts test from context of creating prototype function :(

Wie Sie sehen, ich versuchte Prototyp Getter zu erstellen. Wofür? Nun, wenn Sie schreiben etwas wie folgt aus:

a=function(text)
{
    var b=text;
    this.getText=function(){ return b}
}

... alles soll in Ordnung sein .. aber in der Tat Objekt jedes Mal wenn ich schaffen - ich schaffe getText Funktion, die Speicher verwendet. Ich möchte eine prototypische Funktion im Speicher liegen haben, die das gleiche tun würde ... Irgendwelche Ideen?

EDIT:

habe ich versuchte Lösung von Christoph gegeben, und es scheint, dass seine nur für jetzt bekannte Lösung. Es müssen id Informationen abrufen Wert von Kontext erinnern, aber ganze Idee ist schön für mich :) Id nur eine Sache, sich daran zu erinnern, alles andere einmal im Speicher gespeichert werden können. In der Tat könnte man viele private Mitglieder auf diese Weise speichern und jederzeit nur eine ID verwenden. Eigentlich ist dies mir befriedigend :) (es sei denn, jemand bessere Idee).

someFunc = function()
{
  var store = new Array();
  var guid=0;
  var someFunc = function(text)
  {
    this.__guid=guid;
    store[guid++]=text;
  }

  someFunc.prototype.getValue=function()
  {
    return store[this.__guid];
  }

  return someFunc;
}()

a=new someFunc("test");
b=new someFunc("test2");

alert(a.getValue());
alert(b.getValue());
War es hilfreich?

Lösung

JavaScript traditionell nicht einen Mechanismus für die Eigenschaft versteckt ( "private Mitglieder) vorsah.

Da JavaScript lexikalischer, könnte man immer diese simuliert auf einer pro-Objekt-Ebene durch die Konstruktor Funktion als Verschluss über Ihre "privaten Mitglieder mit und definieren Sie Ihre Methoden im Konstruktor, aber dies wird nicht funktionieren für Methoden definiert in der Eigenschaft prototype Konstruktor.

Natürlich gibt es Möglichkeiten, dies zu umgehen, aber ich würde es nicht empfehlen:

Foo = (function() {
    var store = {}, guid = 0;

    function Foo() {
        this.__guid = ++guid;
        store[guid] = { bar : 'baz' };
    }

    Foo.prototype.getBar = function() {
        var privates = store[this.__guid];
        return privates.bar;
    };

    Foo.prototype.destroy = function() {
        delete store[this.__guid];
    };

    return Foo;
})();

Dies speichert die ‚privaten‘ Eigenschaften in einem anderen Objekt getrennt von Ihrer Foo Instanz. Stellen Sie sicher, destroy() zu rufen, nachdem Sie wih das Objekt fertig sind. Ansonsten, Sie haben gerade einen Speicherverlust


Bearbeiten 2015.12.01: macht ECMAScript6 verbesserte Varianten, die keine manuelle Objekt Zerstörung möglich erfordern, zB durch einen WeakMap oder vorzugsweise ein Symbol , wodurch die Notwendigkeit für einen externen Speicher zu vermeiden insgesamt:

var Foo = (function() {
    var bar = Symbol('bar');

    function Foo() {
        this[bar] = 'baz';
    }

    Foo.prototype.getBar = function() {
        return this[bar];
    };

    return Foo;
})();

Andere Tipps

Methoden auf dem Prototyp nicht „private“ Mitglieder zugreifen können, wie sie in Javascript existieren; Sie brauchen eine Art privilegierter Accessor. Da Sie get deklarieren, wo es lexikalisch b sehen kann, wird es immer wieder zurückkehren, was b bei der Erstellung war.

Nach enorm inspiriert von Christophs Behelfslösung, kam ich mit einem leicht modifizierten Konzept auf, die ein paar Verbesserungen bieten. Auch hier ist diese Lösung interessant, aber nicht unbedingt zu empfehlen. Diese Verbesserungen umfassen:

  • nicht mehr benötigen Setup im Konstruktor ausführen
  • die Notwendigkeit entfernt, um eine öffentliche GUID auf Instanzen speichern
  • hinzugefügt einige syntaktische Zucker

Im Wesentlichen der Trick hier ist das Instanz-Objekt selbst als Schlüssel zum Zugriff auf das zugehörige private Objekt zu verwenden. Normalerweise ist dies nicht möglich, mit einfachen Objekten, da ihre Schlüssel Strings sein müssen. Allerdings konnte ich dies mit der Tatsache tun, dass der Ausdruck ({} === {}) false zurückgibt. Mit anderen Worten: der Vergleichsoperator können erkennen zwischen eindeutigen Objektinstanzen.

Lange Rede kurzer Sinn, können wir zwei Arrays verwenden Instanzen und ihre zugehörigen privaten Objekte zu erhalten:

Foo = (function() {
    var instances = [], privates = [];

    // private object accessor function
    function _(instance) {
        var index = instances.indexOf(instance), privateObj;

        if(index == -1) {
            // Lazily associate instance with a new private object
            instances.push(instance);
            privates.push(privateObj = {});
        }
        else {
            // A privateObject has already been created, so grab that
            privateObj = privates[index];
        }
        return privateObj;
    }

    function Foo() {
        _(this).bar = "This is a private bar!";
    }

    Foo.prototype.getBar = function() {
        return _(this).bar;
    };

    return Foo;
})();

Sie finden die Funktion _ oben bemerkt. Dies ist die Accessorfunktion ahold des privaten Objekt zu greifen. Es funktioniert träge, so dass, wenn Sie es mit einer neuen Instanz aufrufen, wird es ein neues privates Objekt on the fly erstellen.

Wenn Sie nicht den _ Code für jede Klasse duplizieren möchten, können Sie dies lösen, indem es sich in einer Fabrik Funktion Verpackung:

function createPrivateStore() {
    var instances = [], privates = [];

    return function (instance) {
        // Same implementation as example above ...
    };
}

Jetzt können Sie es für jede Klasse nur eine Zeile reduzieren:

var _ = createPrivateStore();

Auch hier haben Sie sehr vorsichtig sein, mit dieser Lösung, da es können erstellen Speicherlecks, wenn Sie nicht implementieren und eine Funktion zerstören rufen, wenn nötig.

Mit modernen Browsern einige ES6 Technologien Annahme, können Sie WeakMap zu bekommen um das GUID Problem verwenden. Dies funktioniert in IE11 und oben:

// Scope private vars inside an IIFE
var Foo = (function() { 
    // Store all the Foos, and garbage-collect them automatically
    var fooMap = new WeakMap();

    var Foo = function(txt) { 
        var privateMethod = function() { 
            console.log(txt); 
        };
        // Store this Foo in the WeakMap
        fooMap.set(this, {privateMethod: privateMethod}); 
    } 

    Foo.prototype = Object.create(Object.prototype); 
    Foo.prototype.public = function() { 
        fooMap.get(this).p(); 
     } 
     return Foo; 
 }());

 var foo1 = new Foo("This is foo1's private method");
 var foo2 = new Foo("This is foo2's private method");
 foo1.public(); // "This is foo1's private method"
 foo2.public(); // "This is foo2's private method"

WeakMap nicht Referenzen speichern, um jeden Foo, nachdem sie gelöscht wird oder fällt aus Umfang, und da es Objekte als Schlüssel verwendet, brauchen Sie nicht GUIDs zu Ihrem Objekt zu befestigen.

Persönlich glaube ich nicht wirklich, wie die Lösung mit der guid, weil es die Entwickler zwingt sie zusätzlich zu dem Laden zu erklären und es im Konstruktor zu erhöhen. In großen JavaScript-Anwendungsentwickler möglicherweise vergessen, dies zu tun, was recht fehleranfällig ist.

Ich mag Peter Antwort aufgrund der Tatsache, ziemlich viel, dass Sie die privaten Mitglieder des Kontext zugreifen können (diese). Aber eine Sache, die ich sehr viel stört, ist die Tatsache, dass der Zugriff auf private Mitglieder in einer o (n) Komplexität getan. Tatsächlich in Array den Index ein Objekt zu finden, ist ein linearer Algorithmus. Betrachten Sie dieses Muster für ein Objekt verwenden möchten, die 10000 mal instanziiert wird. Dann könnten Sie 10000 Instanzen jedes Mal durchlaufen Sie ein privates Mitglied zugreifen möchten.

Um zu privaten Geschäften in einem o für den Zugriff auf (1) die Komplexität, gibt es keine andere Möglichkeit, als guids zu verwenden. Aber um nicht mit der guid Erklärung und Inkrementierung und zu verwenden, um den Kontext für den Zugriff auf den privaten Informationsspeicher I geändert Peters Fabrik Muster wie folgt zu stören:

createPrivateStore = function () {
var privates = {}, guid = 0;

return function (instance) {
    if (instance.__ajxguid__ === undefined) {
        // Lazily associate instance with a new private object
        var private_obj = {};
        instance.__ajxguid__ = ++guid;
        privates[instance.__ajxguid__] = private_obj;
        return private_obj;
    }

    return privates[instance.__ajxguid__];
}

}

Der Trick hier ist zu berücksichtigen, dass die Objekte, die die nicht haben ajxguid Immobilien sind noch nicht behandelt. Tatsächlich könnte man manuell die Eigenschaft festgelegt, bevor das Geschäft zum ersten Mal zugegriffen wird, aber ich denke, es gibt keine magische Lösung.

Ich glaube, wirkliche Privatsphäre ist überbewertet. Virtuelle Privatsphäre ist alles, was benötigt wird. Ich denke, die Verwendung von _privateIdentifier ein Schritt in der richtigen Richtung, aber nicht weit genug, weil Sie noch mit einer Auflistung aller _privateIdentifiers in intellisense Pop-ups vorgestellt sind. Ein weiterer und besserer Schritt ist ein Objekt im Prototyp und / oder die Konstruktorfunktion erstellen für Ihre nahezu privaten Felder und Methoden aus den Augen wie so Absonderungs:

  // Create the object
  function MyObject() {}

  // Add methods to the prototype
  MyObject.prototype = {

    // This is our public method
    public: function () {
      console.log('PUBLIC method has been called');
    },

    // This is our private method tucked away inside a nested privacy object called x
    x: {
      private: function () {
        console.log('PRIVATE method has been called');
      }
    },

  }

// Create an instance of the object
var mo = new MyObject(); 

Jetzt, wenn der Coder-Typ "mo." Intellisense wird nur die öffentliche Funktion und „x“. So sind alle privaten Mitglieder nicht dargestellt sind, aber hinter „x“ versteckt so dass es unwahrscheinlich, dass für einen Codierer versehentlich ein privates Mitglied nennen, weil sie aus dem Weg gehen müssen werden und geben Sie „mo.x.“ private Mitglieder zu sehen. Dieses Verfahren vermeidet auch die Intellisense von der Auflistung mit mehreren privaten Mitgliedernamen überladen zu werden, sie alle hinter dem einzigen Punkt „x“ versteckt.

Ich weiß, dass dieser Thread jetzt wirklich wirklich alt, aber dachte, diese Lösung für jedes von Interesse, indem Sie sein könnte:

const Immutable = function ( val ) {
    let _val = val;

    this.$ = {
        _resolve: function () {
            return _val;
        }
    };
};
Immutable.prototype = {
    resolve: function () {
        return this.$._resolve();
    }
};

Im Wesentlichen der internen versteckt _VAL vor Manipulation und macht eine Instanz dieses Objekt unveränderlich.

Ich habe eine neue Bibliothek zu ermöglichen, private Methoden auf der Prototypkette geschaffen. https://github.com/TremayneChrist/ProtectJS

Beispiel:

var MyObject = (function () {

  // Create the object
  function MyObject() {}

  // Add methods to the prototype
  MyObject.prototype = {

    // This is our public method
    public: function () {
      console.log('PUBLIC method has been called');
    },

    // This is our private method, using (_)
    _private: function () {
      console.log('PRIVATE method has been called');
    }
  }

  return protect(MyObject);

})();

// Create an instance of the object
var mo = new MyObject();

// Call its methods
mo.public(); // Pass
mo._private(); // Fail
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top