2012-02-25 200 views
0

爲什麼這兩個不同的代碼產生不同的結果?使用回調的函數上下文

我的意思是在第一個代碼中定義的foo2和在第二個代碼中的callback是相同的,它們在foo內的相同上下文中執行。

首先代碼:

var foo = function() { 
    var bar = 2; 
    var foo2 = function() { 
    console.log("bar: ", bar); 
    } 
    foo2(); 
} 

foo() // 2 

二碼:

var foo = function (callback) { 
    var bar = 2; 
    callback(); 
} 

var callback = function() { 
    console.log(bar); 
} 

foo(callback); // ReferenceError: bar is not defined 
+0

'bar'只在聲明函數'foo'的內部可見。在第二種情況下''foo'中沒有定義'callback'。 Google for'javascript closures'。 – biziclop 2012-02-25 22:40:40

回答

1

簡短的回答,只是因爲你調用從某處的功能,它並不意味着功能的訪問中所定義的一切你在哪個範圍呢。它可以訪問定義的範圍內的所有內容。在第一種情況下,當定義爲時,它可以訪問bar。在第二個示例中,當它是定義爲時,它沒有訪問bar,因此在調用它時發生抱怨。

龍答案:https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope

2

在第二功能,酒吧超出範圍 - 它僅在函數存在爲「foo()」;在函數「callback()」中,bar不存在,這就是爲什麼你得到的bar沒有定義的錯誤。我要改變它接受一個參數,打印參數,像這樣:

var foo = function (callback) { 
    var bar = 2; 
    callback(bar); 
} 

var callback = function (bar) { 
    console.log(bar); 
} 

這樣,回調將打印無論是在酒吧的價值傳遞。另一種方式來做到這一點(取決於您的應用程序,但一般可以認爲不太推薦)是定義吧作爲一個全局變量,無論是功能之外:

var bar = 2; 

var foo = function (callback) { 
    callback(); 
} 

var callback = function() { 
    console.log(bar); 
} 

兩種方法都可行,但第一種方法比較好封裝你的代碼而不是使用全局變量。

編輯:這是第一個方法,它最好不要使用兩種不同的用途「欄中的」變量名,只是可讀性的緣故減少混亂的版本:

var foo = function (callback) { 
    var bar = 2; 
    callback(bar); 
} 

var callback = function (myBarParam) { 
    console.log(myBarParam); 
} 

希望這是有幫助!

0

在這兩個示例中,您將聲明bar到函數foo的上下文中。 此變量將在foo上下文中以及其所有「子上下文」中可用。

在第一個示例中,您在foo上下文中聲明第二個函數,因此您可以訪問bar

在第二個示例中,未在foo上下文中聲明回調。 bar不可用於回叫,它不存在。

1

在第一種情況下foo2foo的內部定義,因此它可以訪問foo有權訪問的所有當地人。當它綁定bar它無法在foo2中找到它,然後查找foo並使用它在那裏找到的那​​個。

callback的情況下,它定義在foo之外。因此,它不能看到任何foo本地人,而是總結了值是不確定的

0

嘗試

var foo = function (callback) { 
    var bar = 2; 
    callback(bar); 
} 

var callback = function (baz) { 
    console.log(baz); 
} 

foo(callback); 

看出區別:什麼是bar內FOO,是baz內回調 - 以前,這是不確定的

1

由於功能範圍。 (含義變量只能在聲明的範圍內訪問,或者在範圍鏈中聲明(繼續閱讀))

在您的第二個示例中,這變成了clare。 callback()在i全局作用域中聲明。當foo()然後調用callback()時,bar變量將不可見,因爲bar是在另一個函數(foo())中聲明的。如果你已經在函數之外聲明瞭bar(在全局範圍內),它可以從任何地方訪問,也就是說在任何函數內部都可以訪問。

這會工作:

var bar = 2; 

var foo = function() { 
    callback(); 
} 

var callback = function() { 
    console.log(bar); 
} 

foo(); 

在傻冒第一個例子,但是你可以訪問酒吧,即使它不是foo2的()中聲明。這很簡單,因爲如果JavaScript引擎找不到您嘗試使用的變量,它會在「父」函數(或範圍)中查找相同的變量。這被稱爲範圍鏈。