Aufbau von Funktionen/Objekten. Verständnisfrage
Siri
- javascript
Hallo,
ich hab Molilys überaus interessante "Einführung in JavaScript" gelesen und mich damit auseinander gesetzt. Alles habe ich aber auch nach mehrmaligem lesen nicht verstanden.
Variante A:
function Konstruktor1 () {
//privat
k1var1 = "test1";
// öffentlich
this.k1var2 = "test2";
//privat
k1methode1 = function() {
alert (k1var1+"-"+this.k1var2);
}
//öffentlich
this.k1methode2 = function() {
alert (k1var1+"-"+this.k1var2);
}
}
var instanz1 = new Konstuktor1();
instanz1.k1methode2(); // geht
instanz1.k1methode1(); // geht nicht
Variante B:
function Konstruktor2 () {
//privat
var k2var1 = "test3";
// öffentlich
k2var2 = "test4";
//privat
function k2methode1() {
alert (k2var1);
}
//öffentlich
return {
k2methode2: function() {
alert (k2var1);
}
}
}
var instanz2 = new Konstuktor2();
instanz2.k2methode2(); // geht
instanz2.k2methode1(); // geht nicht
Beide Schreibweisen erlauben die Deklaration von privaten und öffentlichen Variablen/Methoden. Wo liegt der Unterschied? Ist es eine Frage des persönlichen Stils? Oder gibt es bestimmte Einsatzzwecke für die eine der Varianten besser geeignet ist als die andere?
Grüße
Siri
Hallo,
Beide Schreibweisen erlauben die Deklaration von privaten und öffentlichen Variablen/Methoden. Wo liegt der Unterschied?
Normalerweise gibt ein Konstruktor nichts explizit mit »return« zurück, denn »new Konstruktor« gibt automatisch das damit neu erzeugte Instanzobjekt zurück.
Ein Konstruktor *kann* ein anderes Objekt als die Instanz zurückgeben, i.d.R. besteht dazu aber kein Grund. Die zweite Variante ist daher unüblich. Wahrscheinlich verwechselst du sie mit dem Module-Pattern oder rein funktionaler Erzeugung von Objekten (letztere behandle ich in meiner Einführung nicht). Dann würde man aber nicht mit »new« arbeiten:
function createFoo () {
function privateFunc () {}
return {
func: function () {
privateFunc();
}
};
}
var foo = createFoo();
foo.func();
Manche propagieren einen solchen funktionalen Stil, weil er verschiedene Vorteile hat (siehe dazu Douglas Crockfords »JavaScript: The Good Parts«).
Bei einem normalen Konstruktor, der mit new aufgerufen wird, gibt es i.d.R. kein return-Statement. Man greift darin über »this« auf das bereits erzeugte Instanzobjekt zurück.
Mathias
Hallo,
vielen Dank für die Erläuterung!
function createFoo () {
function privateFunc () {}
return {
func: function () {
privateFunc();
}
};
}var foo = createFoo();
foo.func();
Könnte man also sagen, dass die obige Variante "statisch" ist?
Grüße
Siri
function createFoo () {
function privateFunc () {}
return {
func: function () {
privateFunc();
}
};
}var foo = createFoo();
foo.func();
>
> Könnte man also sagen, dass die obige Variante "statisch" ist?
Inwiefern statisch? Was bedeutet das? Im Gegensatz zu dynamisch?
Mathias
--
[Chaplin - An Application Architecture Using Backbone.js](https://github.com/chaplinjs/chaplin)
Hallo,
Könnte man also sagen, dass die obige Variante "statisch" ist?
Inwiefern statisch? Was bedeutet das? Im Gegensatz zu dynamisch?
Wenn man einen hinkenden Vergleich zu Java ziehen möchte. Wenn ich also die Methoden einer Klasse statisch aufrufe, ohne vorher ein Objekt erzeugt zu haben.
Grüße
Siri
Wenn man einen hinkenden Vergleich zu Java ziehen möchte. Wenn ich also die Methoden einer Klasse statisch aufrufe, ohne vorher ein Objekt erzeugt zu haben.
Dieses Wort verwendet man in diesem Zusammenhang in JavaScript nicht. Es handelt sich um einfache Objekte mit Funktionen als Eigenschaften. Der Vergleich zu Klassen mit statischen Methoden passt da vorne und hinten nicht. Es *wird* ja ein Objekt erzeugt und eine Funktion daran gehängt.
Das Konzept wäre eher auf einfache Objekt-Literale anwendbar:
var Foo = {
func: function () {}
};
In meiner Einführung vergleiche ich das aber eher mit Singletons, weil das Objekt einen Status haben kann.
Wenn man in JS von statischen Eigenschaften spricht, meint man meist Eigenschaften des Konstruktors selbst. Der ist ja auch nur ein Funktionsobjekt, das Eigenschaften haben kann.
function Konstruktor () {}
Konstruktor.statischeEigenschaft = 'foo';
Aber das ist terminologisch nicht so sauber. In JS gibt es einfach Objekte, und Funktionen sind Objekte erster Klasse. Was da eher herausfällt ist das Aufrufen von Funktionen mittels »new«.
Mathias
gruss Siri,
Beide Schreibweisen erlauben die Deklaration von privaten und öffentlichen
Variablen/Methoden. Wo liegt der Unterschied? ...
...
Variante A ist eine Konstruktorfunktion, die über den [new] Operator und den
den Bezug auf [this] Instanzen ihres eigenen Typs erstellt.
(new Konstruktor1) instanceof Konstruktor1
ist in jedem Fall wahr.
...
Variante A:
function Konstruktor1 () {
//privat
k1var1 = "test1";
/*
ganz böse ... die Zuweisung von "test1" auf [k1var1] erfolgt im globalen Namensraum.
Nur ein vorangestelltes [var] zwingt [k1var1] in den lokalen Scope der Funktion [Konstruktor1].
/
//local
var k1var1 = "test1";
/
Kapselung wird durch den lokalen Scope der Variable und dem Aufruf von [Konstruktor1] erreicht.
Siehe dazu molilys Erläuterungen zu [Closure]s.
*/
// öffentlich
this.k1var2 = "test2";
/*
Richtig. [this] bindet die Eigenschaft [k1var2] direkt adressierbar an jede Instanz der
Konstruktor-Funktion [Konstruktor1].
*/
//privat
k1methode1 = function() {
alert (k1var1+"-"+this.k1var2);
}
/*
nein - keineswegs privat, sondern global - siehe Erklärung weiter oben und Korrektur direkt darunter.
*/
var k1methode1 = function() {
alert (k1var1+"-"+this.k1var2);
}
//öffentlich
this.k1methode2 = function() {
alert (k1var1+"-"+this.k1var2);
}
/*
jo.
*/
}
var instanz1 = new Konstuktor1();
instanz1.k1methode2(); // geht
/*
jepp
*/
instanz1.k1methode1(); // geht nicht
/*
richtig - [k1methode1] wurde ja auch im globalen Namensraum angelegt
/
window.k1methode1();
/
... sollte aufrufbar sein und "test1-undefined" liefern ...
... warum? ...
- [k1var1] wurde ebenfall global angelegt und lässt sich nach "test1" auflösen.
- [k1var2] hingegen existiert nicht im globalen namensraum, ...
- ... denn genau dorthin wird [this.k1var2] aus der global angelegten [k1methode1] aufgelöst.
*/
> ...
Die Methode [Konstruktor2] ist keine Konstruktor-Funktion, obwohl der gemeinsame Aufruf von
[new] Operator und [Konstruktor2] aus dem Beispiel der Variante B dies so erscheinen läßt.
`(new Konstruktor2) instanceof Konstruktor2`{:.language-javascript} wird niemals wahr sein.
Warum?
[Konstruktor2] gibt ein durch ein Objekt-Literal erzeugtes Objekt zurück. Dieses Objekt ist
somit keine Instanz von [Konstruktor2]. Als einzige Eigenschaft besitzt dieses Objekt die
Methode [k2methode2], die nur deshalb Zugriff auf die im lokalen Funktions-Scope von [Konstruktor2]
vereinbarte Variable [k2var1] hat, da das zurückgegebene Objekt im selben Scope erzeugt wird.
Siehe dazu wiederum molilys Erläuterungen zu [Closure]s.
> ...
> Variante B:
> ~~~javascript
function Konstruktor2 () {
>
> //privat
> var k2var1 = "test3";
/*
jepp - aber trotzdem bitte "lokal" statt "privat" denken und schreiben.
*/
> // öffentlich
> k2var2 = "test4";
/*
nope - [k2var2] liegt im globalen Namensraum - siehe Erläuterungen zu Beispiel A.
*/
>
> //privat
> function k2methode1() {
> alert (k2var1);
> }
/*
jepp
*/
> //öffentlich
> return {
> k2methode2: function() {
> alert (k2var1);
> }
> }
/*
siehe Erklärung zu Beispiel B.
*/
> }
> var instanz2 = new Konstuktor2();
> instanz2.k2methode2(); // geht
/*
aber nur wegen [link:http://molily.de/js/organisation-module.html#revealing-module@title=Revealing Module Pattern]
*/
> instanz2.k2methode1(); // geht nicht
/*
richtig - [k2methode1] wurde ja auch im globalen Namensraum angelegt
*/
> ...
... Ist es eine Frage des persönlichen Stils? Oder gibt es bestimmte Einsatzzwecke für die eine
der Varianten besser geeignet ist als die andere?
Benutze Konstruktoren, wenn Du ein Typsystem erstellen möchtest, wo Du die Herkunft von Objekten
anhand des [instanceof] Operators bestimmen möchtest. bzw. wenn Deinen Objekten Methoden über die
Delegation durch [Constructor.prototype] zugewiesen werden sollen.
so long - peterS. - pseliger@gmx.net
Hallo,
vielen Dank!
Schwerer Tobak... Da muss ich wohl noch mehr in die Praxis gehen, aber ich denke ich hab jetzt die Grundzüge besser verstanden.
Grüsse
Siri
hallo again Siri
Schwerer Tobak... Da muss ich wohl noch mehr in die Praxis gehen, ...
dann lass doch mal zur Veranschaulichung den folgenden auf das Minimum
reduzierte Code zeilenweise auf eine JavaScript-Konsole los.
var x = function () {var a="a";return {a:a};}; // undefined
x(); // Object -> a: "a"
x() instanceof x // false
new x(); // Object -> a: "a"
new x() instanceof x // false
var x = function () {var a="a"; this.a=a;}; // undefined
x(); // undefined
x() instanceof x // false
new x(); // x -> a: "a"
new x() instanceof x // true
... aber ich denke ich hab jetzt die Grundzüge besser verstanden.
so long - peterS. - pseliger@gmx.net