2015-06-02 9 views
14

Ich bemerkte eine seltsame Sache in Javascript. Betrachten Sie die folgenden:JavaScript-Funktion Kontext falsch

var fn = ''.toUpperCase.call 
console.log(typeof fn); // "function" 
fn(); // Uncaught TypeError: `fn` is not a function 

Die oben genannten wurde auf meiner Chrome Developer Console ausgeführt. Version ist 43.0.2357.81 m.

Der Operator typeof zeigt deutlich, dass fn eine Funktion ist, aber der Fehler schlägt anders vor.

Ich habe festgestellt, dass Function.apply zeigt zumindest einige sinnvolle Fehlermeldung.

Also, wann ist eine Funktion, keine Funktion?

+0

Bitte zeigen * wie * genau Sie rufen "Fn". – deceze

+5

Ich bekomme "undefined ist keine Funktion" beim Aufruf von 'fn', * nicht *' fn ist keine Funktion'. – Darkhogg

+0

@deceze das ist kein Produktionscode..Ich habe zufällig eine Frage gesehen, über die ich nachgedacht habe. –

Antwort

19

Kontext in Javascript wird immer durch die Art und Weise Anruf eine Funktion eingerichtet.

var fn = ''.toUpperCase.call 

Dieser ordnet die prototypische Implementierung der call Funktion fn. Wenn Sie jetzt fn() anrufen, gibt es keinen Kontext für den Anruf. call würde versuchen, das Funktionsobjekt aufzurufen, mit dem es verknüpft war. Dieser Kontext wird jedoch zum Zeitpunkt des Anrufs festgelegt. Da Sie zum Zeitpunkt des Anrufs keinen Kontext angeben, gibt eine interne Komponente von call einen Fehler aus.

Sie müssten dies tun:

fn.call(''.toUpperCase) 

Das ist richtig, Sie call die call Funktion, einen Kontext zur Gründung, nämlich die toUpperCase Funktion String. In diesem speziellen Fall würde dies zu einem anderen Fehler innerhalb toUpperCase führen, da es nicht an einen bestimmten Kontext gebunden ist. Sie müssten diesen Kontext ausdrücklich auch begründen:

var fn = ''.toUpperCase.call 
fn.call(''.toUpperCase.bind('')) 

Auch How does the "this" keyword work?

+0

also denken Sie, [meine Antwort] (http://stackoverflow.com/questions/30594471/array-prototype-map-is-not-a-function-when-passing-a-function-generated-by-funct/30594762 # 30594762) ist die Antwort auf die verknüpfte Frage auch? –

+0

@Amit Ja, im Grunde sagst du das Gleiche. – deceze

1

So, when is a function, not a function?

Die Funktion ist eine Funktion, aber Sie ausführen es nicht richtig, wie in den Kommentaren und der Antwort erklärt von @deceze

I noticed a weird thing in javascript.

Sie scheinen durch die Nachricht verwirrt, die Sie in die Umwelt gelangen, in dem Sie getestet, ist die Nachricht nicht ganz korrekt.

Uncaught TypeError: fn is not a function

Die aktuelle stabile Version von Chrom (40.0.2214.91 auf meinem Linux installieren, Chrom schlägt fehl, ohne dass Änderungen an den Einstellungen auf meiner Hardware laufen), Chrom die Umgebung zu sein, auf das Sie getestet, einen scheinbar richtigen Fehler gibt Nachricht, die mehr Sinn macht.

Uncaught TypeError: undefined is not a function 

So fragten Sie/wollen eine ernsthafte Frage stellen oder waren Sie gerade ein wenig Spaß an einem Fehler in einer Version von Chrom Stossen?

+2

'40.0.2214.91' ist nicht die aktuelle stabile Version von Chrome. ['43.0.2357.81' ist] (http://googlechromereleases.blogspot.com/2015/06/stable-update-for-chrome-os.html). Die Paketquelle, von der Sie Chrome erhalten, ist nicht aktuell.Ich möchte auch den entscheidenden Punkt erwähnen, dass (selbst wenn der OP die Antwort auf diese Frage wusste, bevor er fragt), der Wunsch, eine Sammlung von Informationen über diesen sehr verwirrenden Fehler zu erstellen, ist weit entfernt von "Stossen Spaß". – apsillers

+1

Ich habe noch viel zu tun, anstatt etwas Chrom zu machen. Und zu Ihrer Information, ich stieß auf dieses Zeug beim Beantworten [hier] (http://stackoverflow.com/questions/30594471/array-prototype-map-is-not-a-function-when-passing-a-function-generated- by-funkt/30594762 # 30594762) und nicht jeder verwendet die Chrome-Version, die Sie verwenden (und ich Chrome nicht manuell aktualisieren, passiert es automatisch) und danke für Ihre Antwort. Danke für den Kommentar über meiner auch. –

+0

Auf Fedora 19 ist es 40.0.2214.91, die automatisch mit YUM aus einem Paket-Repository aktualisiert, ich habe nicht vor, es selbst zu bauen (und ich erinnere mich nur daran ist Chrom und nicht Chrom). Ich verstehe, dass verschiedene Betriebssysteme verschiedene stabile Versionen haben und es Unterschiede geben muss. Ok, du hast diese Information nicht in deine Frage aufgenommen, also hast du wirklich versucht zu überprüfen, ob du eine andere Frage richtig beantwortet hast? Oder ich verstehe immer noch nicht wirklich, was diese Frage ist oder welche Art von Antwort erwarten Sie? – Xotic750

2

deceze's answer ist richtig, ich möchte es nur aus einem anderen Blickwinkel erklären.

Ihre fn ein Verweis auf Function.prototype.call ist, die mit einer Funktion als this Referenz aufgerufen werden muss, in diesem Fall ist der Kontext für call ist String.prototype.toUpperCase, die durch ''.toUpperCase

Obendrein vererbt wurde, String.prototype.toUpperCase Außerdem muss mit einem bestimmten Kontext die Zeichenfolge in Großbuchstaben aufgerufen werden.

Hier ist eine andere Art zu schreiben, was Sie wollten, die Ihnen helfen kann zu verstehen, was vor sich geht.

var str = 'aaa'; 
 
    var upper = ''.toUpperCase; 
 
    var fn = upper.call; 
 
    // Now we have to specify the context for both upper and fn 
 
    console.log(fn.call(function() { return upper.call(str)})); // AAA

In Ihrem Beispiel fn() versucht call zu nennen, aber es ist nicht der Kontext spezifiziert, die typischerweise standardmäßig das window Objekt aber in diesem Fall ist es es nur undefined macht, das ein Trigger seltsamer Fehler in Chrome (wie Sie entdeckt haben), aber Firefox ist klarer über das Problem,

+0

developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call –