Denken Sie zunächst daran, dass JavaScript in erster Linie eine prototypische Sprache und keine klassenbasierte Sprache ist 1 . Foo
ist keine Klasse, es ist eine Funktion, die ein Objekt ist. Sie können ein Objekt aus dieser Funktion mithilfe des new
Schlüsselworts instanziieren , mit dem Sie etwas Ähnliches wie eine Klasse in einer Standard-OOP-Sprache erstellen können.
Ich würde vorschlagen, die __proto__
meiste Zeit zu ignorieren, da es keine browserübergreifende Unterstützung bietet, und sich stattdessen darauf zu konzentrieren, zu lernen, wie es prototype
funktioniert.
Wenn Sie eine Instanz eines Objekts aus einer Funktion 2 erstellt haben und auf eines ihrer Elemente (Methoden, Attribute, Eigenschaften, Konstanten usw.) zugreifen, fließt der Zugriff durch die Prototyphierarchie, bis entweder (a) das gefunden wird Mitglied, oder (b) findet keinen anderen Prototyp.
Die Hierarchie beginnt mit dem aufgerufenen Objekt und durchsucht dann das Prototypobjekt. Wenn das Prototypobjekt einen Prototyp hat, wird es wiederholt, wenn kein Prototyp vorhanden undefined
ist, zurückgegeben.
Beispielsweise:
foo = {bar: 'baz'};
console.log(foo.bar); // logs "baz"
foo = {};
console.log(foo.bar); // logs undefined
function Foo(){}
Foo.prototype = {bar: 'baz'};
f = new Foo();
console.log(f.bar);
// logs "baz" because the object f doesn't have an attribute "bar"
// so it checks the prototype
f.bar = 'buzz';
console.log( f.bar ); // logs "buzz" because f has an attribute "bar" set
Es sieht für mich so aus, als hätten Sie diese "grundlegenden" Teile zumindest schon ein wenig verstanden, aber ich muss sie explizit machen, nur um sicherzugehen.
In JavaScript ist alles ein Objekt 3 .
Alles ist ein Objekt.
function Foo(){}
definiert nicht nur eine neue Funktion, sondern ein neues Funktionsobjekt, auf das mit zugegriffen werden kann Foo
.
Aus diesem Grund können Sie mit auf Foo
den Prototyp zugreifen Foo.prototype
.
Was Sie auch tun wird mehr Funktionen auf Foo
:
Foo.talk = function () {
alert('hello world!');
};
Auf diese neue Funktion kann zugegriffen werden mit:
Foo.talk();
Ich hoffe, dass Sie jetzt eine Ähnlichkeit zwischen Funktionen eines Funktionsobjekts und einer statischen Methode feststellen.
Stellen Sie sich vor f = new Foo();
, Sie erstellen eine Klasseninstanz, Foo.prototype.bar = function(){...}
definieren eine gemeinsame Methode für die Klasse und Foo.baz = function(){...}
definieren eine öffentliche statische Methode für die Klasse.
ECMAScript 2015 führte eine Vielzahl von syntaktischen Zuckern für diese Art von Deklarationen ein, um deren Implementierung zu vereinfachen und gleichzeitig die Lesbarkeit zu verbessern. Das vorherige Beispiel kann daher wie folgt geschrieben werden:
class Foo {
bar() {...}
static baz() {...}
}
was erlaubt bar
, als bezeichnet zu werden:
const f = new Foo()
f.bar()
und baz
genannt werden als:
Foo.baz()
1: class
war ein "Future Reserved Word" in der ECMAScript 5-Spezifikation , aber ES6 bietet die Möglichkeit, Klassen mithilfe des class
Schlüsselworts zu definieren .
2: Im Wesentlichen eine Klasseninstanz, die von einem Konstruktor erstellt wurde, aber es gibt viele nuancierte Unterschiede, die ich Sie nicht irreführen möchte
3: Primitive Werte , zu denen Boolesche Werte , Zahlen und Zeichenfolgen gehören undefined
, null
sind technisch gesehen keine Objekte, da es sich um Sprachimplementierungen auf niedriger Ebene handelt. Boolesche Werte, Zahlen und Zeichenfolgen interagieren immer noch mit der Prototypenkette, als wären sie Objekte. Für die Zwecke dieser Antwort ist es daher einfacher, sie als "Objekte" zu betrachten, obwohl sie nicht ganz sind.
Foo.talk = function ...