2016-04-05 12 views
1

Ich dachte, ich verstehe Schließungen, aber ich denke nicht. Hier ist ein Codebeispiel, das das Problem zeigt, in das ich hineingeraten bin. Ich würde erwarten, dass der Code "Text" auf die Konsole drucken würde.Schließung Missverständnis

var inner = function() { 
    console.log(text); 
}; 

var outer = function(cb) { 
    var text = 'text'; 
    cb(); 
}; 

Ich führe die äußere Funktion mit der inneren Funktion als cb. In diesem Fall bekomme ich var Text undefiniert. Ich dachte, dass die innere Funktion immer noch einen Verweis auf die Textvariable wegen der js-Schließung haben würde.

//Run outer with a cb of inner. 
outer(inner); 

Erprobt mit einer anonymen Funktion als ein cb und gibt den gleichen Fehler von Text undefined.

//Anonymous 
outer(function() { 
    console.log(text); 
}); 

Irgendwelche Ideen, was mir hier fehlt? Ich benutze die Schließung in anderen Bereichen meines Programms ohne Probleme, aber ich verstehe nicht ganz, was vor sich geht.

Antwort

3

Das Problem hier ist weniger das Ergebnis von Verschlüsse, da es Umfang ist ... und ich bevorzuge es, JavaScript Umfang in Bezug auf Eltern/Kind-Beziehungen zu denken.

Jede Bereichseinheit (z. B. eine Funktion) hat Zugriff auf Objekte, die in den ererbten "Parent-Bereichen" definiert sind (Sichtbarkeit wird nach oben verschoben) - "Parent-Bereiche" können jedoch nicht innerhalb von untergeordneten Bereichen und untergeordneten Bereichen angezeigt werden Bereich kann nicht ineinander sehen.

enter image description here

Das Bild oben ist generisch und schamlos von Google Bilder gestohlen, sondern dient zu erklären, dass „A“ ist die Mutter Umfang; "B" und "C" wurden innerhalb des übergeordneten Bereichs definiert. "D" und "E" sind im Rahmen von "B" definiert - also kann "C" nicht "D" oder "E" sehen.

In Ihrem Beispiel ist der Bereich "Parent" der Kontext, in dem diese beiden Funktionen definiert wurden (vermutlich window). Alles definiert innerhalb des Bereichs (Kontext) einer der "Kinder" Methoden können die Dinge im Bereich (Kontext) darüber definiert definiert - so der Code innerhalb outer() ist bekannt, dass inner() existiert (beide wurden in definiert der übergeordnete Bereich), aber keine Funktion kann sehen, was innerhalb des anderen existiert. (Anmerkung: der übergeordneten Bereich (vermutlich window) kann auch nicht sehen, was in jedem dieser Funktionen definiert wurde, es kennt nur die Funktionen existieren.)

Aber weil die Sicht nur nach oben bewegt, wird der Umfang innerhalb inner() nicht wissen text weil es innerhalb outer() definiert wurde.

2

text ist nicht definiert - diese Frage nicht ein Verschluss ist, es ist eine Frage der nicht einen Parameter auf Ihren Rückruf übergeben:

var outer = function(cb) { 
    var text = 'text'; 
    cb(text); //note the parameter pass in here 
}; 

outer(function(textParam) { //and now the callback passed in accepts a param 
    console.log(textParam) //name this param whatever you want! 
}); 
1

Es gibt keine (relevanten) Schließung, wenn cb innerhalb outer aufrufen.

Wenn Sie erstelltinner innerhalb outer Sie über text schließen würde, und Sie würden ihren Wert sehen, wenn inner – Aufruf aber du bist nicht.

Die text innerhalb inner ist die globale text.

+0

Danke, verdeutlicht das Problem für mich. Ich werde auch die Schließungen genauer unter die Lupe nehmen müssen. – Elliot

0

Mit Closures können Funktionen auf Variablen in dem Bereich zugreifen, in dem sie definiert sind, nicht auf den Bereich, in dem sie aufgerufen werden.

Wenn Sie Ihr Beispiel ändern, würde das Folgende "geänderten Text" drucken.

var text = 'some text'; 
var inner = function() { 
    console.log(text); 
}; 

text = 'changed text' 

var outer = function(cb) { 
    cb(); 
}; 

outer(inner); 
0

Sie sollten auch den Begriff studieren, um die Situation zu verstehen. Der Umfang einer Variablen/Funktion wird durch ihre Position innerhalb des Quellcodes definiert.

Eine Schließung wird erstellt, wenn eine Funktion innerhalb einer zweiten/äußeren Funktion deklariert und dann von dieser Funktion zurückgegeben wird (zweite/äußere). In Ihrem Fall ist die inner Funktion nicht innerhalb der outer Funktion deklariert.

Sie könnten neu ordnen Sie Code, um einen Verschluss zu bilden, wie:

function outer() { 
    var text = 'text'; 

    function inner(){ 
     console.log(text); 
    }; 

    return inner; 
} 

var foo = outer(); 

foo();  // text