• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Private Variablen

  • Ersteller Ersteller gform
  • Erstellt am Erstellt am
G

gform

Guest
Hallo,

ich schreibe gerade eine kleine "Klasse" in Javascript und will das Problem das ich dabei habe mal in diesem einfachen Beispiel zeigen.

Code:
function Number() {
    var n = 0;
    
    this.add = function(x) {
        n += x;
    };
    
    this.getN = function() {
        return n;
    };
}

var num = new Number;
num.add(10);
num.getN(); // 10

Das funktioniert auch, jedoch steht im MDN, dass man aus Performancegründen die beiden Methoden add und getN nicht im Funktionsrumpf definieren soll, sondern so:

Code:
function Number() {
    var n = 0;
}


Number.prototype = {
    add: function(x) {
        n += x;
    },
    
    getN: function() {
        return n;
    }
};

Nun haben aber add und getN keinen Zugriff auf n. Wie kann man das umgehen?
this.n kommt nicht in Frage, da n privat sein soll.

Gruß
 
Erstell private und priviligierte Funktionen innerhalb deiner Klasse.
Von Aussen greifst dann auf die priviligierte Funktion zu, welche dann wiederum die private Funktion aufruft.

Ein gutes Beispiel hierfür findest du auf: OOP in JavaScript || Methoden
 
Danke für die Antwort.
Privilegierte Methoden habe ich doch im ersten Codeblock, die versuche ich aber nicht zu verwenden, weil MDN davon abgeraten hat.
 
Ah Sorry...

Tja leider gibt es keine andere Möglichkeit! Funktionen die über Prototype einer Klasse hinzugefügt wurden haben nun mal einfach keinen Zugriff auf privat deklarierte Variablen innerhalb der Klasse. Das ist bei Javascript nun mal so und da führt auch kein Umweg zu deinem Vorhaben.
 
Ich habe mal jetzt etwas herumexperimentiert und bin auf eine, wenn auch nicht sehr schöne, Lösung gekommen.
Die Idee: nur Getter und Setter im Funktionsrumpf schreiben und all die anderen Methoden über prototype definieren. Damit man von außen nicht auf den Setter zugreifen kann, habe ich das alles in einen Closure gepackt und dort eine Variable intern definiert, die standardmäßig auf false gesetzt ist. Immer wenn eine Methode den Setter aufruft, setzt die die Variable intern auf true und danach wieder auf false.
Hier der Code:

Code:
(function() {


var intern = 0;


window.Lorem = function(value) {
    var v = value;
    
    this.getV = function() {
        return v;
    };
    
    this.setV = function(newV) {
        if (intern)
            v = newV;
    };
};


Lorem.prototype = {
    set5 : function() {
        intern = 1;
        this.setV(5);
        intern = 0;
    }
};


})();

Und hier ein Test:

Code:
var l = new Lorem(10);
console.log(l.getV()); // 10
l.set5();
l.setV(1000);
console.log(l.getV()); // 5

Wie findet ihr die Idee?
Geht es vielleicht auch etwas einfacher?

EDIT:
Noch intuitiver erscheint es beim programmieren/lesen, wenn man das Verändern des Werts von intern und das Aufrufen vom Setter in eine extra Funktion auslagert.

Code:
function setV(v) {
    intern = 1;
    this.setV(v);
    intern = 0;
}

Und dann sieht die Methode set5 so aus:

Code:
Lorem.prototype = {
    set5 : function() {
        setV.call(this, 5);
    }
};
 
Zuletzt bearbeitet von einem Moderator:
Ist im Endeffekt dasselbe wie in deinem ersten Beitrag. Du greifst von aussen auf priviligierte Funktionen zu!
 
Nein, wenn man von außen auf setV zugreift, hat es keinen Effekt.
 
In JavaScript ist alles möglich. Man muss nur überlegen:
PHP:
(function (window, undefined) {
	var KlasseName = function () {
		var name = "";
		var KlasseName = function () {
		};
		KlasseName.prototype = {
			getName: function () {
				return name;
			},
			setName: function (new_name) {
				name = new_name;
			}
		};
		return new KlasseName();
	};
	window.KlasseName = KlasseName;
})(window);

var Objekt1 = new KlasseName();
var Objekt2 = new KlasseName();
Objekt1.setName("Berta");
Objekt2.setName("Klaus");
console.log(Objekt1.getName()); // Berta
console.log(Objekt2.getName()); // Klaus

So arbeite ich jedenfalls immer.
 
Das tut aber genau das was ich vermeiden will.

  1. es steht alles im Funktionsrumpf
  2. man kann von außen auf setName zugreifen
 
Du hast wohl offenbar keine Ahnung von JavaScript, hast auch das falsch verstanden, was in MDN steht und wahrscheinlich auch den Code falsch verstanden, den ich dir gegeben habe.
Es ist nichts falsch daran, Closures im "Funktionsrumpf" zu haben. Das ist sogar das Prinzip von JavaScript. Was allerdings schlecht ist, ist öffentliche Methoden direkt an das Objekt zu binden ohne den Prototype. Das ist es, was abgesehen von der etwas leidenden Performance unsauber ist.

In Java oder PHP setzt du schließlich auch die Methoden in die Klasse und nicht außerhalb. Und bei Vererbung hast du auch keinen Zugriff auf private Variablen ;)
Die saubere Art und Weise, das zu machen mit deinem Beispiel ist so:
PHP:
(function (window, undefined) {
	var Lorem = function (value) {
		var v = value;
		var Lorem = function () {};
		var setV = function (newV) {
			v = newV;
		};
		Lorem.prototype = {
			getV: function () {
				return v;
			},
			set5: function () {
				setV(5);
			},
			setV: function () {
				// Nichts, kann auch fallen gelassen werden, falls du die Funktion gar nicht aufrufbar machen wills.
			}
		};
		return new Lorem();
	};
	window.Lorem = Lorem;
})(window);

In dem Beispiel werden die sichtbaren UND privaten Methoden auf derselben Ebene definiert. Der eigentlich "Rumpf" (das Wort hat keinen Sinn in JavaScript-Objektorientierung) ist hier leer:
PHP:
var Lorem = function () {};
 
Danke für die Hilfe!

Es ist nichts falsch daran, Closures im "Funktionsrumpf" zu haben. Das ist sogar das Prinzip von JavaScript. Was allerdings schlecht ist, ist öffentliche Methoden direkt an das Objekt zu binden ohne den Prototype. Das ist es, was abgesehen von der etwas leidenden Performance unsauber ist.

Ja, dann habe ich es wohl falsch verstanden.

Der eigentlich "Rumpf" (das Wort hat keinen Sinn in JavaScript-Objektorientierung)

Warum? Damit ist doch nur das zwischen den geschweiften Klammern gemeint oder hat es noch eine spezielle Bedeutung?
 
Naja, von einem Rumpf spricht man bei 'ner Klasse in Java oder PHP, einer Methode oder Funktion. Aber in JavaScript ist der Unterschied zwischen diesen ganzen Dingen gar nicht gegeben. Wie du unschwer erkennen kannst, ist alles irgendwie eine Funktion und in dem Beispiel hier sind es sogar sehr wenige Funktionen. Es kann oft passieren, dass man eine Funktion in einer Funktion in einer Funktion in einer Funktion in einer Funktion (usw.) hat und es trotzdem irgendwie noch guter Stil ist. Und man kann in JavaScript auch nicht von Klassen sprechen. In JavaScript gibt es Objekte, keine Klassen und jedes Objekt hat einen Prototypen, der in einem Objekt aber überladen werden kann =)

Das Ganze wirkt wahrscheinlich bestimmt verwirrend, aber es gibt nicht viele Leute, die in den Genuss von sauberem JavaScript geraten sind ^^
 
Zurück
Oben