所以使用下面的代码,我向自己证明了嵌套函数确实获得了外部函数参数的副本:
var o = {};
(function(a,b,c,x){
x.f = function(){
return a.toString()+b.toString()+c.toString();
}
})(7,4,2,o);
o.f();
代码产生
742
这意味着o.f
函数从匿名函数中获取a,b和c的副本。否则,我会得到undefinedundefinedundefined
我的问题是,
答案 0 :(得分:9)
您观察到的是词汇范围。这意味着JavaScript中某个范围内变量的绑定取决于变量在代码中的显示位置。它总是如此,并且在任何级别都是如此。唯一的主要例外是this
值,动态范围而不是词法范围。动态范围意味着函数中的变量取决于函数的调用方式和时间。 (见Lexical Scoping and Dynamic Scoping。)
示例:
var o = {
a: function() {
var x = 5;
console.log(this, x);
function b() {
console.log(this, x);
}
b();
}
};
o.a();
此示例的结果将是:
{Object o} 5
{window} 5
换句话说,第一个console.log
会将this
记录为o
对象的引用,而第二个console.log
会将this
记录为window
对x
对象的引用。但是,两者都会将5
记录为等于this
。在没有上下文的非严格模式下调用window
时,this
的值为x
。因此this
不是词法范围,而是其他变量,如this
。要详细了解arguments
的行为,请参阅A Short Overview of this
。
直接回答您的问题:
是的,除了function a() {
var x = 1;
console.log('a:', x);
return function b() {
var y = 2;
console.log('b:', x, y);
return function c() {
console.log('c:', x, y);
};
};
}
var foo = a(); // => logs 'a: 1'
var bar = foo(); // => logs 'b: 1 2'
bar(); // => logs 'c: 1 2'
和{{1}}之外,它是正确的,它根据函数的调用方式而改变。它不必是一个对象,所有变量都是词法范围的。
你可以尽可能深入 - 内部函数总是可以访问其外部函数的变量。
{{1}}
这实际上是另一个被称为closures的主题的一部分,当你从另一个函数中返回一个函数时会发生这种情况。
我已经链接了几个资源。另一个好的:
MDN: Functions and function scope(特别是关于Nested Functions and Closures的部分)。
此外,您可以通过阅读闭包上的任何内容获益,而且您可能还想查找词汇范围。
答案 1 :(得分:1)
您需要做的就是阅读闭包。 http://en.wikipedia.org/wiki/Closure_(computer_science)内部函数没有得到该变量的副本,它得到对该变量的引用。例如:
var o = {};
(function(a,b,c,x){
x.f = function(){
return a.toString()+b.toString()+c.toString();
}
a++;
})(7,4,2,o);
o.f();
产量
842
编辑:好的,也许这不是所有,你需要阅读。我只是觉得值得证明这个概念对于许多语言来说并不陌生。
答案 2 :(得分:1)
我在代码中使用这个概念时犯了一个愚蠢的错误,错误地将参数重新声明为变量。发布在这里,以防它帮助其他人。
(function(){
var outerFunction=function(varA){
console.debug('value of varA in outer function '+varA);
var innerFunction = function(){
console.debug('value of varA in inner function '+varA);
}
innerFunction();
};
outerFunction("hi");
var buggyOuterFunction=function(varA){
console.debug('value of varA in buggy outer function '+varA);
var buggyInnerFunction = function(){
var varA = varA || "hello"; //BUG - do not redeclare
console.debug('value of varA in buggy inner function '+varA);
}
buggyInnerFunction();
};
buggyOuterFunction("hi");
})();
输出:
value of varA in outer function hi
value of varA in inner function hi
value of varA in buggy outer function hi
value of varA in buggy inner function hello
答案 3 :(得分:0)
this
绑定,则this
绑定到全局(窗口)对象。这被普遍认为是javascript中一个令人震惊的缺陷。当心。