Das Wichtigste dabei ist, dass, da Javascript eine dynamische Sprache ist, jedes Objekt im Wesentlichen nur eine verherrlichte Hash-Map ist ( mit wenigen Ausnahmen ). Auf alles in einem Javascript-Objekt kann auf zwei Arten zugegriffen werden - in Klammernotation und Punktnotation.
Ich werde schnell die beiden Notationen durchgehen und den ersten Teil Ihrer Frage beantworten, und dann komme ich zum zweiten Teil.
Klammernotation
Dieser Modus ähnelt eher dem Zugriff auf Hashmaps und Arrays in anderen Programmiersprachen. Mit dieser Syntax können Sie auf jede Komponente (Daten (einschließlich anderer Objekte) oder Funktion) zugreifen .
Genau das tun Sie in Ihrem Beispiel. Sie haben 'a'
eine Zeichenfolge (und kein Zeichenliteral, wie es in einer Sprache wie C ++ der Fall wäre).
Mit der Klammernotation greifen Sie auf die toUpperCase
Methode zu. Der Zugriff darauf reicht jedoch immer noch nicht aus. Durch einfaches Eingeben alert
von beispielsweise Javascript wird die Methode nicht aufgerufen. Es ist nur eine einfache Aussage. Um die Funktion aufzurufen, müssen Sie die Klammer hinzufügen: alert()
Zeigt ein einfaches Dialogfeld an undefined
, das keine Parameter enthält. Wir können dieses Wissen nun nutzen, um Ihren Code zu entschlüsseln.
alert('a'.toUpperCase());
Welches ist viel besser lesbar.
Ein guter Weg, dies ein bisschen besser zu verstehen, ist die Ausführung des folgenden Javascript:
alert(alert)
Dies ruft alert
auf, indem es auch ein Funktionsobjekt übergibt alert
, ohne auch die zweite Warnung auszuführen. Was angezeigt wird (zumindest in Chrome 26), ist Folgendes:
function alert() { [native code] }
Berufung:
alert(alert())
zeigt zwei aufeinanderfolgende Meldungsfelder mit undefined
. Dies ist leicht zu erklären: Das Innere alert()
wird zuerst ausgeführt, zeigt undefined
(weil es keine Parameter hatte) und gibt nichts zurück. Die äußere Warnung erhält den Rückgabewert der inneren Warnung - was nichts ist - und wird auch undefined
in einem Meldungsfeld angezeigt.
Probieren Sie alle Fälle auf jsFiddle aus!
Punktnotation
Dies ist der Standardansatz, mit dem auf Mitglieder eines Objekts mit dem .
Operator dot ( ) zugegriffen werden kann . So würde Ihr Code in Punktnotation aussehen:
alert('a'.toUpperCase())
Viel besser lesbar. Wann sollten wir also die Punktnotation verwenden und wann sollten wir die Klammernotation verwenden?
Vergleich
Der Hauptunterschied zwischen den beiden Methoden ist die Semantik. Es gibt auch einige andere Details, aber ich werde gleich darauf zurückkommen. Am wichtigsten ist, was Sie tatsächlich tun möchten. Als Faustregel gilt, dass Sie die Punktnotation für gut etablierte Felder und Methoden eines Objekts verwenden und die Klammernotation, wenn Sie Ihr Objekt tatsächlich als Hash-Map verwenden .
Ein gutes Beispiel dafür, warum diese Regel so wichtig ist, finden Sie in Ihrem Beispiel. Da der Code die Klammernotation an einer Stelle verwendet, an der die Punktnotation viel sinnvoller gewesen wäre, ist der Code schwerer zu lesen. Und das ist eine schlechte Sache, denn Code wird viel öfter gelesen als geschrieben .
In einigen Fällen müssen Sie die Klammernotation verwenden, auch wenn die Punktnotation sinnvoller war:
Wenn ein Mitglied eines Objekts einen Namen hat, der ein oder mehrere Leerzeichen oder andere Sonderzeichen enthält, können Sie die Punktnotation nicht verwenden: foo.some method()
funktioniert nicht, funktioniert aber foo["some method"]()
;
Wenn Sie dynamisch auf die Mitglieder eines Objekts zugreifen müssen, stecken Sie auch in der Klammernotation fest.
Beispiel:
for(var i = 0; i < 10; ++i) {
foo["method" + i]();
}
Unter dem Strich sollten Sie die Klammer-Syntax verwenden, wenn Sie das Objekt als Hash-Map verwenden ( foods["burger"].eat()
), und die Punkt-Syntax, wenn Sie mit "tatsächlichen" Feldern und Methoden arbeiten ( enemy.kill()
). Da Javascript eine dynamische Sprache ist, kann die Grenze zwischen "tatsächlichen" Feldern und Methoden eines Objekts und "anderen" darin gespeicherten Daten ziemlich verschwommen werden. Aber solange Sie sie nicht auf verwirrende Weise mischen, sollte es Ihnen gut gehen.
Nun zum Rest Ihrer Frage (endlich !: P).
Wie kann ich sicher sein, dass method immer Mitglied von obj sein wird?
Das kannst du nicht. Versuch es. Versuchen Sie, derp
eine Zeichenfolge aufzurufen . Sie erhalten eine Fehlermeldung in den Zeilen:
Uncaught TypeError: Object a has no method 'derp'
Es ist eine generische Funktion, ANY-Methoden für JEDES Objekt aufzurufen. Bedeutet dies jedoch, dass die angegebene Methode bereits ein implizites Mitglied des angegebenen Objekts ist?
Ja, in deinem Fall müsste es sein. Andernfalls erhalten Sie den oben genannten Fehler. Allerdings müssen Sie nicht haben zu verwenden , return obj[method]();
in der callMethod()
Funktion. Sie können Ihre eigene Funktionalität hinzufügen, die dann von der Kartenfunktion verwendet wird. Hier ist eine fest codierte Methode, mit der alle Buchstaben in Großbuchstaben umgewandelt werden:
function makeCap()
{
return function(obj) {
return obj.toUpperCase();
}
}
var caps2 = map(['a', 'b', 'c'], makeCap()); // ['A','B','C']
console.log(caps2)
Der Code in dem Tutorial, mit dem Sie verknüpft haben, verwendet Teilfunktionen . Sie sind ein kniffliges Konzept für sich. Mehr über dieses Thema zu lesen sollte helfen, die Dinge klarer zu machen, als ich sie jemals machen könnte.
Hinweis: Dies ist der Code der Kartenfunktion, die vom Code in der Frage verwendet wird. Quelle hier .
function map(arr, iterator) {
var narr = [];
for (var i = 0; i < arr.length; i++) narr.push(iterator(arr[i], i));
return narr;
}
arr[5]
. Wenn Zahlen gültige Bezeichnernamen haben, können Sie die Punktnotation verwenden :arr.5
.