JavaScript überrascht mich immer wieder und dies ist eine weitere Instanz. Ich bin gerade auf einen Code gestoßen, den ich zuerst nicht verstanden habe. Also habe ich es getestet und bin zu folgendem Ergebnis gekommen:
alert('a'['toUpperCase']()); //alerts 'A'
Nun muss dies offensichtlich sein, wenn toUpperCase()
es als Mitglied vom Typ string definiert ist, aber es ergab für mich anfangs keinen Sinn.
Wie auch immer,
- funktioniert das, weil
toUpperCase
ein Mitglied von 'a' ist? Oder ist hinter den Kulissen noch etwas los? Der Code, den ich gelesen habe, hat folgende Funktion:
function callMethod(method) { return function (obj) { return obj[method](); //**how can I be sure method will always be a member of obj** } } var caps2 = map(['a', 'b', 'c'], callMethod('toUpperCase')); // ['A','B','C'] // ignoring details of map() function which essentially calls methods on every // element of the array and forms another array of result and returns it
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?
Ich bin sicher, dass mir ein ernsthaftes Verständnis des Grundkonzepts der JavaScript-Funktionen fehlt. Bitte helfen Sie mir, dies zu verstehen.
quelle
arr[5]
. Wenn Zahlen gültige Bezeichnernamen haben, können Sie die Punktnotation verwenden :arr.5
.5['toString']()
.Antworten:
Um es zu brechen.
.toUpperCase()
ist eine Methode vonString.prototype
'a'
ist ein primitiver Wert, wird jedoch in seine Objektdarstellung konvertiertSo
ist der Zugriff über die Klammernotation auf dem Grundstück
toUpperCase
vonString.prototype
. Da diese Eigenschaft auf eine Methode verweist , können wir sie durch Anhängen aufrufen()
quelle
foo.bar
undfoo['bar']
sind gleich, so dass der Code, den Sie gepostet haben, der gleiche ist wieBei der Verwendung
foo[bar]
(beachten Sie das Fehlen von Anführungszeichen) verwenden Sie nicht den Literalnamen,bar
sondern den Wert, den die Variablebar
enthält. Wenn Sie also diefoo[]
Notation anstelle von verwenden,foo.
können Sie einen dynamischen Eigenschaftsnamen verwenden.Werfen wir einen Blick auf
callMethod
:Zunächst wird eine Funktion zurückgegeben, die
obj
als Argument dient. Wenn diese Funktion ausgeführt wird, wirdmethod
dieses Objekt aufgerufen . Die gegebene Methode muss also entweder entweder für sichobj
selbst oder irgendwo in ihrer Prototypenkette existieren.Wenn
toUpperCase
diese Methode von stammtString.prototype.toUpperCase
, wäre es ziemlich dumm, für jede einzelne vorhandene Zeichenfolge eine separate Kopie der Methode zu haben.quelle
Sie können entweder mit
.propertyName
Notation oder["propertyName"]
Notation auf die Mitglieder eines Objekts zugreifen . Das ist das Merkmal der JavaScript-Sprache. Um sicherzustellen, dass sich das Mitglied im Objekt befindet, überprüfen Sie einfach, ob es definiert ist:quelle
Grundsätzlich behandelt Javascript alles als Objekt, oder vielmehr kann jedes Objekt als Wörterbuch / assoziatives Array angesehen werden. Und Funktionen / Methoden werden für das Objekt genauso definiert - als Eintrag in diesem assoziativen Array.
Im Wesentlichen referenzieren / rufen Sie also die Eigenschaft 'toUpperCase' des Objekts 'a' (in diesem Fall ein Zeichenfolgentyp) auf (beachten Sie ' () ').
Hier ist ein Code auf meinem Kopf:
quelle
anyObject['anyPropertyName']
ist das gleiche wieanyObject.anyPropertyName
wennanyPropertyName
es keine problematischen Charaktere gibt.Siehe Arbeiten mit Objekten im MDN.
Die
toUpperCase
Methode ist an den Typ String angehängt. Wenn Sie eine Funktion für einen primitiven Wert aufrufen'a'
, wird sie hier automatisch zu einem Objekt heraufgestuft, hier zu einem String :Sie können sehen, dass die Funktion vorhanden ist, indem Sie sie protokollieren
String.prototype.toUpperCase
.quelle
Also in Javascript
objects
sindobjects
. Das heißt, sie sind von dieser Art{}
. Objekteigenschaften können mit folgenden Optionen festgelegt werden:a.greeting = 'hello';
odera['greeting'] = 'hello';
. Beide Wege funktionieren.Das Abrufen funktioniert genauso.
a.greeting
(ohne Anführungszeichen) ist'hello'
,a['greeting']
ist'hello'
. Ausnahme: Wenn die Eigenschaft eine Zahl ist, funktioniert nur die Klammermethode. Die Punktmethode funktioniert nicht.So
'a'
ist ein Objekt mit'toUpperCase'
Eigenschaft, die eigentlich eine Funktion ist. Sie können die Funktion abrufen und anschließend so'a'.toUpperCase()
oder so aufrufen: oder'a'['toUpperCase']()
.Aber imo wäre der bessere Weg, die Kartenfunktion zu schreiben, wie
var caps = ['a','b','c'].map( function(char) { return char.toUpperCase(); } )
Wer braucht die
callMethod
Funktion dann?quelle
Jedes JavaScript-Objekt ist eine Hash-Tabelle, sodass Sie auf seine Mitglieder zugreifen können, indem Sie einen Schlüssel angeben. Wenn eine Variable beispielsweise eine Zeichenfolge ist, sollte sie die Funktion toUpperCase haben. Sie können es also mit aufrufen
Also, durch Inline-Str, könnten Sie unten haben
quelle
toUpperCase ist eine Standard-Javascript-Methode: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/toUpperCase
Der Grund dafür
'a'['toUpperCase']()
ist, dass die Funktion toUpperCase eine Eigenschaft des Zeichenfolgenobjekts ist'a'
. Sie können die Eigenschaften eines Objekts mitobject[property]
oder referenzierenobject.property
. Die Syntax 'a''toUpperCase' gibt an, dass Sie auf die Eigenschaft 'toUppercase' des String-Objekts 'a' verweisen und es dann aufrufen ().quelle
Jemand könnte ein Objekt übergeben, das
toUpperCase
; odertoUpperCase
, die keine Funktion istIm ersten Fall wird ein Fehler ausgegeben, da der Zugriff auf eine nicht vorhandene Eigenschaft zurückgegeben
undefined
wird und wir nichtundefined
als Funktion aufrufen können.Im zweiten Fall wird ein Fehler ausgegeben, da wir wiederum keine Nichtfunktion als Funktion aufrufen können.
Denken Sie daran, dass JavaScript eine sehr lose typisierte Sprache ist. Es erfolgt nur eine geringe oder keine Typprüfung, es sei denn und bis dies erforderlich ist. Der von Ihnen angezeigte Code funktioniert in bestimmten Fällen, da in diesen Fällen das übergebene Objekt eine Eigenschaft namens
toUpperCase
, dh eine Funktion, hat.Die Tatsache, dass das
obj
Argument nicht die richtigen Eigenschaften aufweist, stört JavaScript sozusagen überhaupt nicht. Es nimmt eine abwartende Haltung ein und gibt keinen Fehler aus, bis zur Laufzeit ein tatsächliches Problem auftritt.quelle
Fast alles in Javascript kann als Objekt behandelt werden. In Ihrem Fall fungiert das Alphabet selbst als Zeichenfolgenobjekt und
toUpperCase
kann als Methode aufgerufen werden. Die eckigen Klammern sind nur eine alternative Möglichkeit, auf Objekteigenschaften zuzugreifen, und da diestoUpperCase
eine Methode ist, wird die einfache Klammer()
neben dem['toUpperCase']
Formen benötigt['toUpperCase']()
.'a'['toUpperCase']()
ist äquivalent zu'a'.toUpperCase()
quelle
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 Eingebenalert
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 anundefined
, das keine Parameter enthält. Wir können dieses Wissen nun nutzen, um Ihren Code zu entschlüsseln.Welches ist viel besser lesbar.
Ein guter Weg, dies ein bisschen besser zu verstehen, ist die Ausführung des folgenden Javascript:
Dies ruft
alert
auf, indem es auch ein Funktionsobjekt übergibtalert
, ohne auch die zweite Warnung auszuführen. Was angezeigt wird (zumindest in Chrome 26), ist Folgendes:Berufung:
zeigt zwei aufeinanderfolgende Meldungsfelder mit
undefined
. Dies ist leicht zu erklären: Das Innerealert()
wird zuerst ausgeführt, zeigtundefined
(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 auchundefined
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: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 aberfoo["some method"]()
;Wenn Sie dynamisch auf die Mitglieder eines Objekts zugreifen müssen, stecken Sie auch in der Klammernotation fest.
Beispiel:
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).
Das kannst du nicht. Versuch es. Versuchen Sie,
derp
eine Zeichenfolge aufzurufen . Sie erhalten eine Fehlermeldung in den Zeilen: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 dercallMethod()
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: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 .
quelle
Wenn Sie fragen, wie es tatsächlich funktioniert, wie ich es gelesen habe. Ok, das ist eine einfache mathematische Funktion. Um es zu verstehen, müssen Sie sich die ASCII-Tabelle ansehen. Womit jedem Buchstaben ein numerischer Wert zugewiesen wird. Um dies zu verbergen, verwendet der Wettbewerb einfach eine logische Anweisung, um dies zu verbergen. Beispiel: Wenn (ChcrValue> 80 && charValue <106) // Dies ist die Menge der Kleinbuchstaben, dann charValue = charValue - 38; // der Abstand zwischen dem unteren und dem oberen Satz
So einfach ist das. Ich habe mich nicht wirklich darum gekümmert, die richtigen Werte nachzuschlagen. Dies verschiebt jedoch im Grunde alle Kleinbuchstaben in Großbuchstaben.
quelle
'a'['toUpperCase']()
arbeiten. Aber das Missverständnis ist verständlich, wenn jemand die Frage nicht gelesen hat.text-transform: uppercase
hinzugefügt wurden, war ich am Ende, wie JS es geschafft hat, den Fall zu ändern, Zweifel auszuräumen und ein oder zwei Dinge zu lernen. Vielen Dank.