2012-02-25 215 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引擎找不到您尝试使用的变量,它会在“父”函数(或范围)中查找相同的变量。这被称为范围链。