2014-05-08 16 views
16

Ich lese Eloquent JavaScript (The new edition) und ich erreichte den Teil auf höherer Ordnung Funktionen und ich bin verwirrt, was im folgenden Code passiert.Höherwertige Funktionen in Javascript

function noisy(f) { 
    return function(arg) { 
    console.log("calling with", arg); 
    var val = f(arg); 
    console.log("called with", arg, "- got", val); 
    return val; 
    }; 
} 
noisy(Boolean)(0); 
// → calling with 0 
// → called with 0 - got false 
  1. Warum der Aufruf der Funktion ist laut wie das? Ist (Boolean) eine Besetzung? Eine Besetzung für was? der Rückgabewert? oder das Argument? Warum nicht (Boolean) laut (0) wenn es der Rückgabewert ist. Oder laut ((Boolean) 0), wenn das Argument das Argument ist, das geworfen wird.

    noisy(Boolean)(0) 
    
  2. Was passiert in dieser Zeile? Wo ist f() definiert?

    var val = f(arg); 
    

Antwort

19
  1. Boolean ist eine Funktion. Es ist die Funktion, die Sie indirekt über noisy aufrufen. Ein bisschen verwirrend, ich weiß, weil es wie der Name eines Typs aussieht. Aber in JavaScript sind diese anfänglich begrenzten Dinge (Boolean, Number, String usw.) Funktionen. Wenn Sie (ohne mit new) aufrufen, versucht es, das Argument, das Sie es gaben, in einen boolean primitiven Wert zu konvertieren, und gibt das Ergebnis zurück. (Siehe §15.6.1 in der Spezifikation.)

  2. f ist der Name des Arguments in der noisy-Funktion.

Funktionen in JavaScript sind erstklassige Objekte. Sie können sie wie jedes andere Objekt in andere Funktionen als Argumente übergeben.

Wenn Sie das tun

noisy(Boolean)(0) 

Es gibt zwei Dinge geht. Erstens:

// (In effect, we're not really creating a variable...) 
var x = noisy(Boolean); 

Das gibt uns eine Funktion, die, wenn sie aufgerufen wird, Boolean mit dem Argument nennen wir es geben, während auch jene console.log Aussagen zu tun. Diese Funktion wird in noisy (return function(arg)...) erstellt.

Dann rufen wir die Funktion:

x(0); 

Und das ist, wenn Sie die Konsole-Ausgabe. Da Boolean(0)false ist, sehen Sie Boolean diesen Wert zurückgeben.

Hier ist ein viel einfacheres Beispiel:

function foo(bar) { 
    bar(); 
} 
function testing() { 
    alert("testing got called"); 
} 
foo(testing); 

Dort bin ich das Bestehen der Funktion testing in foo. Der Argumentname, den ich dafür innerhalb foo verwende, ist bar. Die Zeile bar(); ruft die Funktion auf.

+0

@Crowder: Aber dann, wenn diese anfänglich begrenzten Dinge (Boolean, Number, String, und so weiter) sind Funktionen, warum var x = Zahl (5); Warnung (typeof x); // Nummer; Warnung (x instanceof Function); // false –

+0

@ShirgillAnsari: Alles ist detailliert in [der Spezifikation] (http://www.ecma-international.org/ecma-262/6.0/index.html). 'var x = Nummer (5)'. Sie rufen die Funktion 'Number' als Funktion auf (nicht als Konstruktor). Die Spezifikation [sagt] (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-number-constructor-number-value), dass, wenn Sie das tun, es sein Argument in a umwandelt Nummer wenn nötig (besseres Beispiel: 'var x = Nummer (" 42 ")'). Für den zweiten Alarm, warum sollten Sie erwarten, dass 'x' eine Funktion ist? –

+0

Oh, ich sehe, da es in einen primitiven booleschen Wert umgewandelt wurde, deshalb sagten Sie, warum erwarte ich, dass x eine Funktion ist? Ist es das, was du meintest? –

9

Eine Funktion ohne() ist die eigentliche Funktion. Eine Funktion mit() ist ein Aufruf der Funktion. Beachten Sie auch, dass JavaScript eine lose typisierte Sprache ist, sodass Sie keine Variablentypen deklarieren. Ich habe Ihrem Beispiel einige Kommentare hinzugefügt, um zu versuchen und zu helfen.

// We define a function named noisy that takes in an argument named f. We are expecting f to be a function but this isn't enforced till the interpreter throws an error. 
function noisy(f) { 
// Noisy returns a single item, an anonymous function. That anonymous function takes in an argument named arg 
    return function(arg) { 
    console.log("calling with", arg); 
// Our anonymous function then takes f (It can use f because its defined inside noisy, see closures for more details) and invokes it with the argument arg and stores the result in a variable named val. 
    var val = f(arg); 
    console.log("called with", arg, "- got", val); 
// It now returns val 
    return val; 
    }; 
} 

Also dann laut (Boolean) (0) funktioniert wie dieses

f ist die Funktion Boolean

laut kehrt eine Funktion wie diese

function(arg) { 
    var val = Boolean(arg); 
    return val; 
} 

So, jetzt haben wir

unsere zurückgegebene Funktion (0)

, die wie normale führt

function(0) { 
    var val = Boolean(0); // false 
    return val; 
} 
5

ich geworden bin relativ neu in JS und ich habe auch gerade durch Eloquent Javascript zu lesen und ich fand es leichter zu verstehen, wenn ich den Aufruf der Funktion verstanden (Ihr Punkt 1) zu beantworten:

noisy(Boolean)(0); 

die noisy(Boolean) erstellt eine neue Funktion und die (0) ist, nachdem sie, weil sie als Argument in diese neue Funktion übergeben wird. Wenn Sie auf die größer ist als Beispiel verweisen:

function greaterThan(n) { 
    return function(m) { return m > n; }; 
} 
var greaterThan10 = greaterThan(10); 
console.log(greaterThan10(11)); 

Es auf diese Weise auch genannt werden könnte:

greaterThan(10)(11); 

Ich hoffe, dass klärt Ihre erste Frage, warum es auf diese Weise genannt.

Für die zweite Frage. Die f in:

var val = f(arg); 

ist die Funktion, die in Booleannoisy übergeben wurde, als noisy(Boolean) eingegeben wurde. Es wurde dann als Argument in der geräuschvollen Funktion verwendet. Ich wusste auch nicht, dass Boolean eine Funktion für sich sein kann und nicht nur ein Datentyp. Wie andere gesagt haben - es konvertiert das Argument, das Sie ihm gegeben haben, in einen booleschen Wert und gibt das Ergebnis zurück.

Daher val wird Boolean(arg), die Boolean(0) wird, die false auswertet. Wenn Sie versuchen, rufen Sie noisy(Boolean)(1); Sie sehen es true zurückgeben. Die console.log("called with", arg, "- got", val); protokolliert einfach das Argument (0 in diesem Fall) und das Ergebnis der Auswertung (falsch).

Tatsächlich hat es die boolesche Funktion in eine geändert, die das Argument und das Ergebnis protokolliert und das Ergebnis zurückgibt.

Ich hoffe, das hilft. Nur das Schreiben hat mir geholfen, mein eigenes Verständnis zu verstehen.

0

Für den Fall, dass Sie immer noch Probleme damit haben, hier ist, wie ich es verstehe (es gab mir auch Kopfschmerzen.

)
function noisy(f) { 
    return function(arg) { 
     console.log("calling with", arg); 
     var val = f(arg); 
     console.log("called with", arg, "- got", val); 
     return val; 
    }; 
} 

noisy(Boolean)(0) 

Eine Funktion ist nur ein ganz normaler Wert. Der vorherige Satz ist der Schlüssel zum Verständnis, was hier vor sich geht.

Unsere laute (f) Funktion ist ein Wert. Es ist, was es zurückgibt.

verrauscht (f) gibt eine Funktion zurück, die ein Argument (arg) akzeptiert.

Rauschen (f) nimmt auch ein Argument (f). Innere Funktionen (von Funktionen aufgerufene Funktionen) haben Zugriff auf Variablen und Argumente, die an die äußere Funktion übergeben wurden.

Wir nennen unsere äußere Funktion und übergeben sie das Argument Boolean. Unsere äußere Funktion gibt ihre innere Funktion zurück, die ein Argument (0) annimmt. Durch das Verständnis des oben Gesagten sollte klar werden, dass laut (Boolean (0)) einfach ein Argument an unsere äußere Funktion, übergeben würde, während nichts an die innere Funktion weitergegeben wird, die von unserer äußeren Funktion zurückgegeben wird.

Es ist wirklich so einfach. Nun, da wir es verstehen, ist es schwer zu glauben, dass es uns anfangs Kopfschmerzen bereitete ... */`