簡體   English   中英

回調函數,閉包和執行上下文

[英]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);
}

這在功能上與您擁有的示例相同: fooabar是作為callback傳入的匿名函數。

為什么調用bar()導致打印1 該變量在foo本地作用域,而bar對此一無所知。

函數只能引用在以下任何一個中聲明的變量:

  1. 功能體,
  2. 函數參數(適用於第一個例子),
  3. 聲明函數的范圍。

換句話說,不考慮調用范圍,因此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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM