[英]callback function, closure and execution context
function a(callback) {
var something = 10;
callback(something);
}
a(function(blabla) {
console.log(blabla); // output 10
});
好吧,我沒有理解這段代碼的問題。
我知道“某些東西”是function a
本地,但是在閉包和事實意義上, 當調用函數時我會創建執行上下文,我也希望在工作之后:
function a(callback) {
var something = 10;
callback();
}
a(function() {
console.log(something);
});
那么究竟發生了什么(為什么第二個例子不起作用)?
顯然,一切都是垃圾收集的,並且在回調函數體中無法訪問。
在第二個示例中,局部變量something
在回調體中是不可訪問的,不是因為它是垃圾收集,而是因為它超出了范圍。
考慮這個反例:
function a(callback) {
callback();
}
var something = 10;
a(function() {
console.log(something);
});
這里有something
在定義回調體的范圍內,所以你可以引用它。 這樣做可以創建一個閉包。
還要考慮這個:
function foo() {
var xyz = 1;
bar();
}
function bar() {
console.log(xyz);
}
這在功能上與您擁有的示例相同: foo
是a
, bar
是作為callback
傳入的匿名函數。
為什么調用bar()
導致打印1
? 該變量在foo
本地作用域,而bar
對此一無所知。
函數只能引用在以下任何一個中聲明的變量:
換句話說,不考慮調用范圍,因此something
被認為是未定義的。
在閱讀你的問題時,聽起來像這里的主要困惑是為什么你可以引用something
內部a
something
,但不是在提供給a
的匿名函數內。
變量something
在函數a
的上下文中定義,而不是在匿名函數內。 因此,當您在匿名函數中引用something
時,它實際上引用了一個隱式全局變量,在這種情況下,該變量未定義。 匿名函數被放置到調用的參數列表中的事實, a
沒有什么區別。
如果您意識到第二個片段大致等同於以下內容,可能會更清楚:
function a(callback) {
var something = 10;
callback();
}
function b() {
console.log(something);
}
a(b);
所以你可以清楚地看到這兩個完全不相關的函數,它們有自己的范圍。
在你的第一個例子中: -
function a(callback) {
var something = 10;
callback(something);
}
a(function(blabla) {
console.log(blabla); // output 10
});
blabla是一個變量,可以作為參數傳遞給a的匿名函數。 因此,某些東西作為函數參數傳遞給回調函數,因此可以在名稱blabla下運行。
但在第二個例子中: -
function a(callback) {
var something = 10;
callback();
}
a(function() {
console.log(something);
});
函數不知道某些東西,因為它不是全局變量/不是函數參數。
因此,當您嘗試訪問未定義的變量時,這是一個js錯誤。
因此,某些東西的范圍僅限於函數a,並且回調函數不可用
簡短的回答:在第二個例子中的回調產生的閉合,將尋找全局變量something
不存在。
比。 第一個例子周圍產生可變的封閉something
中的功能a
。 如果something
的值發生something
變異,再次調用a
將產生不同的值。
考慮以下不同的方式來傳遞回調函數:
var something = "Global something";
function a(callback) {
var something = "Local something";
callback(something);
}
a( console.log ); // "Local something"
根據定義, console.log()
將接受something
通過函數傳遞a
作為第一個參數,並把它打印輸出到屏幕上。 關閉發生在局部變量上。
a( function() {console.log(something)} ); //"Global something"
當你定義一個函數為inline它會創建自己的范圍,並引用了一個局部變量something
。
由於內聯函數沒有捕獲它,函數a
傳遞的something
會被刪除。 在一些更嚴格的語言中,它會拋出一個錯誤,但JS卻沒有。
內聯函數試圖console.log
局部變量something
,這是沒有找到。 搜索全局范圍並找到“Global something”並打印它。 局部變量沒有閉包。
a( function(x) {console.log(x)} ); //"Local something"
內聯函數創建並引用局部變量x
。
但是x
指向函數a
傳遞的something
變量,而something
變量又指向“本地東西”,它被打印出來。 關閉局部變量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.