简体   繁体   English

JavaScript的范围和闭包问题

[英]Issue with scope and closures in JavaScript

My question is really more about scope in JavaScript, rather then closures. 我的问题确实更多地是关于JavaScript的范围,而不是闭包。

Let's take the following code: 让我们看下面的代码:

var f = function () {
    var n = 0;
    return function () {
        return n++;
    };
}();

console.log(f());
console.log(f());

The above code outputs: 上面的代码输出:

0
1

As you can see from the above code, f (self-invoked) returns a function, creating a closure of n . 从上面的代码中可以看到, f (自调用)返回一个函数,创建n的闭包。


So, it works with an anonymous function; 因此,它可以与匿名函数一起使用; thus, I then tried it with a named function: 因此,我随后使用命名函数进行了尝试:

var f2 = function () {
    return n++;
};

var f = function () {
    var n = 0;
    return f2;
}();

console.log(f2()); // <= [n is not defined]

The above code doesn't work, with the error n is not defined . 上面的代码不起作用,错误n is not defined I assume that this is a scoping issue; 我认为这是一个范围界定的问题; but I cannot figure why exactly; 但是我不知道为什么会这样。

Why is it that the scope is the same with an anonymous, inner function but does not work with a named, outer function? 为什么作用域与匿名内部函数相同,但不适用于命名外部函数?

Also, in the second example, am I creating a closure? 另外,在第二个示例中,我是否要创建一个闭包?

The closure is created in the first example because the code in the anonymous function uses a local variable that is declared outside of the anonymous function. 在第一个示例中创建闭包,因为匿名函数中的代码使用在匿名函数外部声明的局部变量。

In the second example the scope of the n variable in the function f2 is already decided when the function is declared. 在第二个示例中,在声明函数时已经确定了函数f2 n变量的范围。 Creating a local variable with the same name doesn't change the meaning of the function, and using the function inside another function doesn't change it's scope. 创建具有相同名称的局部变量不会更改函数的含义,并且在另一个函数中使用该函数也不会更改其范围。 Thus, the function doesn't use the local variable. 因此,该函数不使用局部变量。

There is no way for f2 to figure out where it should take variable n. f2无法确定应将变量n放在何处。

In first example anonymous function is inside function f, in second - outside (f2 instead of anonymous). 在第一个示例中,匿名函数在函数f内部,第二个-外部(f2而不是匿名)。 So, f2 cannot access variable n, because it is in another scope and inaccessible (invisible). 因此,f2无法访问变量n,因为它在另一个范围内并且不可访问(不可见)。 Try put f2 declaration inside f. 尝试将f2声明放入 f中。

In your second example, you are not creating a closure, you are simply returning a global variable. 在第二个示例中,您没有创建闭包,而只是返回一个全局变量。 f2 is not being closed over because it was declared in a more general (in this case, global) scope, and n is declared in a more specific scope. f2尚未结束,因为它是在更一般的范围(在本例中为全局)范围内声明的,而n在更特定的范围内声明。 Closure is possible down the scope chain "funnel," not up, and is only effective when all related entities are defined in the same scope. 闭合可能在作用域链“漏斗”中向下发生,而不是向上,并且仅当所有相关实体都在同一作用域中定义时才有效。

We could rewrite your second example to make it work with a named function: 我们可以重写您的第二个示例,以使其与命名函数一起工作:

var f = function() {
    var n = 0;
    var f2 = function() {
        return n++;
    };
    return f2;
}();
console.log(f());
console.log(f());

This would output, 0 and 1 as your first example did. 如您的第一个示例那样,它将输出0和1。

As the other answers have stated, its not about the function being named or anonymous, its about scope of n and f2. 正如其他答案所指出的那样,它与函数的名称或匿名无关,与n和f2的范围有关。 Since you declared f2 outside of f in your example, it had no access to the variable n declared inside the scope of f. 由于您在示例中在f之外声明了f2,因此它无法访问在f范围内声明的变量n。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM