gruss Olaf,
...
var Foo = function(id) {
this.getId = function() {
return id;
}
}Foo.prototype = new function() {
var that = this;
var getSpecialId = function() {
return that.getId() + 1;
}
this.showSpecialId = function() {
alert(getSpecialId());
}
}myFoo = new Foo(23);
myFoo.showSpecialId(); // -> Fehler 'that.getId is not a function'
> ...
> Ist es möglich, in privaten Methoden innerhalb von Foo.prototype
> auf Methoden oder Eigenschaften von Foo zuzugreifen?
nein, so wie Du es gerne betreiben moechtest, ueberhaupt nicht. die argumente,
die dagegen sprechen, werden Dir ja schon von Mathias in den zwei folgenden,
aus gruenden der linearitaet hier noch mal velinkten und zitierten posts
genannt ...
... aus <https://forum.selfhtml.org/?t=180370&m=1191665> ...
> > wie kann ich denn private Daten, die im Konstruktor gesetzt wurden
> > den Methoden im Prototype-Objekt bekannt machen.
>
... zitat molily:
> JavaScript hat nicht die OOP-Fähigkeiten anderer bekannter Sprachen
> und es ist problematisch, das Konzept der Kapselung auf JavaScript
> zu übertragen. Privatheit gibt es in JavaScript nur durch Closures.
> Das ist erstmal was ganz anderes, ein funktionales statt ein
> objektorientiertes Feature, und ist auch nicht an die Verwendung
> im Zusammenhang mit Konstruktoren und Instanzen gebunden.
>
> Aus funktionaler Sicht ist dein Ausgangsbeispiel mit K.prototype = new function () {}
> eigentlich sehr passend und es wäre auch sinnig, wenn du die durch
> Closure verfügbaren Methoden mit call bzw. apply im Kontext der
> Instanz ausführst. Das wäre m.M.n. JavaScript-typisch, alles andere
> wären Versuche, gänzlich anders organisiertes OOP aus anderen Sprachen
> in JavaScript umzusetzen. Das geht nicht, das ist auch nicht unbedingt
> sinnvoll und wird den Features von JavaScript nicht gerecht.
> ...
... und aus <https://forum.selfhtml.org/?t=180370&m=1191683> ...
> > Man kann Prima in JS private Eigenschaften und Funktionen in
> > der Konstruktorfunktion kapseln
> ...
> > nur eben nicht im Prototype.
> ...
> > Wo siehst du da ein Problem?
>
... zitat molily:
> Ein Problem damit habe ich nicht, jedoch sehe ich ein Problem
> darin, die Denkweise von JavaScript-fremden OOP auf JavaScript-
> OOP zu übertragen, anstatt über Lösungen in der JavaScript-Logik
> nachzudenken.
@Olaf
es stellen sich zwei fragen; warum willst Du an so einer delikaten stelle
modularisierten code schreiben; warum versuchst Du genau dies ueber den
[protoype] des [[Foo]]-constructors zu implementieren.
zuerst fasse ich die ideen des Sprachkonzepts nochmal kurz in eigene worte,
dannach folgen beispielhaft loesungen, die sich schulmaessig an Deinem code
orientieren muessen und damit die frage nach ihrer bedeutung fuer die praxis
nicht beantworten koennen.
- Der als ECMAScript (ECMA 262) standardisierte Sprachkern von JavaScript beschreibt eine moderne, schlanke, objektorientierte aber klassenlose Skriptsprache, die dennoch allen objektorientierten Programmierparadigmen unter anderem auch - aber eben nicht ausschließlich - auf der Basis von Prototypen gerecht wird.
Obwohl im Grunde eine funktionale Skriptsprache, läßt sich in JavaScript sowohl prozedural als auch rein funktional bzw. objektorientiert programmieren.
ECMA 262 kann damit ohne weiteres auch als Multiparadigmensprache bezeichnet werden.
- In JavaScript representieren sich alle Daten bis auf die Typen [Undefined] und [Null] bzw. bis auf die primitiven Werte [boolean], [number] und [string] als Objekte. Funktionen sind ebenfalls Objekte, deren im Funktionsrumpf gebundenen Anweisungen über den call-Operator bzw. über call-Methoden ausgeführt werden.
- Gekapselte Daten sind lokale Werte bzw. Objekte einer Funktion. Diese begrenzte \*Sichtbarkeit\* von Daten kann bei Datenstrukturen durch ineinander verschachtelte Funktionen (Funktion in Funktion) gezielt ausgenutzt und über Referenzierungskonzepte ebenso gezielt getunnelt werden.
- Schon auf dieser Grundlage läßt sich fuer alle nativen JavaScript-Objekte das Signal-Slot-Konzept implementieren, sodaß ereignisorientiertes Programmieren, auch losgelöst von DOM-Events, allein mit den Mitteln des Sprachkerns möglich ist.
- Vererbung wiederum erfolgt in JavaScript ausschließlich über Delegation; entweder direkt über eine der call-Methoden oder implizit über den Objekt- Prototypen eines jeden Objekt-Konstruktors. Letztgenannter leistet dabei die Abstraktion zur Vererbung (im Sinne von \*ist ein\*), während die zuerst angesprochenen Methoden der Umsetzung des Aggregationskonzepts (\*hat ein\*) dienlich sind.
siehe dazu auch den diskussions- bzw. den benutzer-link auf der deutschen wikipedia zu JavaScript:
- [Neues Fass aufmachen: Sprachklassifizierung allgemein und Diskussion der aktuellen Einleitung speziell](http://de.wikipedia.org/wiki/Diskussion:JavaScript#Neues_Fass_aufmachen:_Sprachklassifizierung_allgemein_und_Diskussion_der_aktuellen_Einleitung_speziell)
- [Intro-Sprachkonzept - Sprachklassifizierung - Werte, Objekte des Sprachkerns, Objektstrukturen - Funktionen als Datentypen - Funktionen als Konstruktoren von Objekten eines bestimmten Typs - prototypenbasierte Vererbung](http://de.wikipedia.org/wiki/Benutzer_Diskussion:Pseliger)
eine loesung Deines problems muss besonders absatz 3 beruecksichtigen.
wir suchen ein geeignetes referenzierungskonzept, welches den beiden
fuereinander \*kontextblinden\* modulen genau einen gueltigen kontext
zur verfuegung stellt.
in Deinem beispiel moechtest Du gerne das zusaetzliche verhalten je einer
privaten bzw. oeffentlichen methode [getSpecialId] bzw. [showSpecialId]
zusaetzlich zum verhalten einer jeden [[Foo]]-instanz implementieren.
schon die wortwahl klingt eher nach interface als nach prototypischer
erweiterung - in einem ersten wurf kann das z.b. so aussehen:
~~~javascript
/*
wie immer code bitte mit *copy und paste*
in der [link:http://jconsole.com/@title=jconsole] zum laufen bringen:
*/
var SpecialIdFunctor = (function (that) { // [[SpecialId]] -Functor(, -Interface, -Behavior, ... -Monad?)
var getSpecialId = (function () {
return (that.getId() + 1);
});
this.showSpecialId = (function() {
//alert(getSpecialId());
return getSpecialId();
});
});
var Foo = (function (id) { // [[Foo]] constructor
this.getId = (function () {
return id;
});
});
var myFoo = new Foo(23);
print(myFoo.id); // undefined
print(myFoo.getId()); // 23
print(myFoo.getSpecialId); // undefined
print(myFoo.showSpecialId); // undefined
SpecialIdFunctor.call(myFoo, myFoo); // applying the [Functor](, [Interface], [Behavior], ... [Monad]?) onto [myFoo]
print(myFoo.id); // undefined
print(myFoo.getId()); // 23
print(myFoo.getSpecialId); // undefined
print(myFoo.showSpecialId()); // 24
diese loesung laesst es zu, dass jede einzelne [[Foo]]-instanz um
eigenschaften des hier [[SpecialIdFunctor]] genannten interfaces
erweitert werden kann und eben nicht zwangslaeufig um diese
erweitert wird.
die naechste loesung leitet sich aus dem obigen beispiel ab, setzt
einen dem interface verpflichteten automatismus um, und kapselt dabei
die gesamte funktionalitaet unter dem constructor [[Foo]]:
/*
[link:http://jconsole.com/]
*/
var Foo = (function (/*id*/) { // [[Foo]] constructor wrapper
var SpecialIdFunctor = (function (that) { // [[SpecialId]] -Functor(, -Interface, -Behavior, ... -Monad?)
var getSpecialId = (function () {
return (that.getId() + 1);
});
this.showSpecialId = (function() {
//alert(getSpecialId());
return getSpecialId();
});
});
var FooConstructor = (function (id) { // [[Foo]] constructor
SpecialIdFunctor.call(this, this); // applying the [Functor](, [Interface], [Behavior], ... [Monad]?)
this.getId = (function () {
return id;
});
});
return FooConstructor;
})();
var myFoo = new Foo(23);
print(myFoo.id); // undefined
print(myFoo.getId()); // 23
print(myFoo.getSpecialId); // undefined
print(myFoo.showSpecialId()); // 24
auch im letzten entwurfsmuster gibt es noch genug gruende modularisiert
zu schreiben, auch wenn es im moment auf den ersten blick erstmal nicht
viel mehr als das argument der codepflege hergibt - komplexere anwendungen
koennen hier aber sowohl von kapselung als auch von schnittstellenvererbung
profitieren.
noch mehr spielkram in diese richtung findet sich unter:
- »Mixin: Verhalten durch Delegation über implementierte Interfaces«
- »Objektfunctionen - Vererbung durch Delegation«
- »Vererbung durch Delegation über Interfaces«
- »beispielhafte Zusammenfassung von JavaScript als Sprache der OO.«
so long - peterS. - pseliger@gmx.net
»Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]