Ich weiß, ich bin spät dran, aber hier ist eine kürzere Methode, die mehr in Richtung Ihrer ersten Versuche geht.
a.replace('f', String.call.bind(a.toUpperCase));
Also, wo haben Sie sich geirrt und was ist dieser neue Voodoo?
Problem 1
Wie bereits erwähnt, haben Sie versucht, die Ergebnisse einer aufgerufenen Methode als zweiten Parameter von String.prototype.replace() zu übergeben, anstatt eine Referenz auf eine Funktion zu übergeben
Lösung 1
Das ist leicht genug zu lösen. Einfach das Entfernen der Parameter und Klammern gibt uns eine Referenz anstelle der Ausführung der Funktion.
a.replace('f', String.prototype.toUpperCase.apply)
Problem 2
Wenn Sie den Code jetzt ausführen, erhalten Sie einen Fehler, der besagt, dass undefined keine Funktion ist und daher nicht aufgerufen werden kann. Dies liegt daran, dass String.prototype.toUpperCase.apply tatsächlich eine Referenz auf Function.prototype.apply() über die prototypische Vererbung von JavaScript ist. Also, was wir tatsächlich tun, sieht eher so aus
a.replace('f', Function.prototype.apply)
Was offensichtlich nicht das ist, was wir beabsichtigt haben. Wie weiß es, Function.prototype.apply() auf String.prototype.toUpperCase() auszuführen?
Lösung 2
Indem wir Function.prototype.bind() verwenden, können wir eine Kopie von Function.prototype.call mit seinem Kontext erstellen, der speziell auf String.prototype.toUpperCase festgelegt ist. Jetzt haben wir folgendes
a.replace('f', Function.prototype.apply.bind(String.prototype.toUpperCase))
Problem 3
Das letzte Problem ist, dass String.prototype.replace() mehrere Argumente an seine Ersetzungsfunktion übergibt. Jedoch erwartet Function.prototype.apply(), dass der zweite Parameter ein Array ist, erhält aber stattdessen entweder einen String oder eine Zahl (je nachdem, ob Sie Erfassungsgruppen verwenden oder nicht). Dies würde einen Fehler in der Liste der ungültigen Argumente verursachen.
Lösung 3
Zum Glück können wir einfach Function.prototype.call() (das eine beliebige Anzahl von Argumenten akzeptiert, von denen keines Typbeschränkungen hat) für Function.prototype.apply() substituieren. Wir sind jetzt bei funktionierendem Code angekommen!
a.replace(/f/, Function.prototype.call.bind(String.prototype.toUpperCase))
Bytes sparen!
Niemand möchte 'prototype' mehrmals eingeben. Stattdessen nutzen wir die Tatsache, dass wir Objekte haben, die die gleichen Methoden über die Vererbung referenzieren. Der String-Konstruktor, als Funktion, erbt von der Prototype von Function. Das bedeutet, dass wir String.call für Function.prototype.call substituieren können (eigentlich können wir Date.call verwenden, um noch mehr Bytes zu sparen, aber das ist weniger semantisch).
Wir können auch unsere Variable 'a' nutzen, da ihr Prototyp eine Referenz auf String.prototype.toUpperCase enthält, können wir das mit a.toUpperCase austauschen. Es ist die Kombination der 3 oben genannten Lösungen und dieser Bytemaßnahmen, wie wir den Code oben in diesem Beitrag erhalten.
1 Stimmen
@Erik entferne keine Komponente einer Frage. Ich möchte auch wissen, warum mein Code nicht funktioniert.
2 Stimmen
Evan, ich dachte, ich wäre respektvoll gegenüber deiner Frage. Ich habe nur Dinge entfernt, die unnötig schienen. Da du den Code angegeben hast, den du ausprobiert hast, und es offensichtlich nicht funktioniert hat, wussten die Leute implizit, dass du eine Erklärung brauchst, warum, ohne dass du es sagen musstest (und ungeschickt). Ich versuche nur zu helfen! :)
1 Stimmen
Evan, ist das besser? Ich will nicht nerven. Wenn du erneut zurückrollst, werde ich nicht nochmal bearbeiten, aber könntest du zumindest die Titel- und Tag-Änderungen beibehalten?
0 Stimmen
Technisch gesehen verwende ich überhaupt kein JavaScript, sondern v8 (ECMAScript). Aber ich nehme an, dass die meisten Leute, die danach suchen, nach JavaScript suchen, also ist das in Ordnung für mich.
1 Stimmen
Fühlen Sie sich frei, Tags hinzuzufügen, wenn Sie denken, dass sie dazu gehören.
0 Stimmen
@EvenCarrol und für die Nachwelt: Es ist völlig in Ordnung, die Implementierung von ECMAscript von v8 als "JavaScript" zu bezeichnen, auch wenn es technisch gesehen ein falscher Name ist. Die Unterscheidung für jeden Fall, in dem es nicht um die Implementierung von Netscape oder Mozilla ging, würde einfach zu viel Zeit in Anspruch nehmen und es gibt wirklich keine elegante Möglichkeit, "ECMAscript" mit weniger als 5 klobigen Silben auszusprechen. Nicht zu vergessen ist, dass man technisch gesehen die ECMA-Spezifikation unterstützen kann, aber trotzdem etwas ziemlich anderes als JavaScript oder JScript oder was auch immer Chrome/V8 ihre Version nennt, haben kann, daher wird zumindest behauptet, dass wir in derselben ECMAscript-Familie sind.
0 Stimmen
Ich bin anderer Meinung. Es ist verwirrend und es weiter zuzulassen, macht die Sache noch verwirrender. Javascript macht alle Arten von coolen Sachen, die Ecmascript nicht macht. Ja-Va, Eck-Ma -- bin mir nicht sicher, wo der Unterschied bei den Silben liegt. Die beiden zu verwechseln, ist so ähnlich wie C zu bezeichnen, als sei es eine Untermenge von C++, C++.
1 Stimmen
Ein verwirrender Aspekt dieser Frage für mich war, dass die Frage ein Sonderfall ist, bei dem die Erfassungsgruppe auch der gesamte übereinstimmende Ausdruck ist. Ist dies nicht der Fall, ergeben sich unerwartete Ergebnisse, da sie das gesamte Muster behandeln.