如何在闭包中完成绑定?

时间:2013-03-29 14:51:11

标签: javascript closures symbol-table name-binding

function f() { return s; } // works fine though no `s` is defined yet !

var s=1;
f(); // 1

delete s;

var s=2;
f(); // 2 

(function() {
var s=3;
f(); // 2 and not 3 which means lexical scoping is at play (?)
})();

首先,您可以关闭尚未定义的变量(s)。如果使用词法(静态)范围,那怎么可能呢?

第二,删除原始s后,f()可以找到新的s。这是否意味着闭包绑定到变量名称而不是引用或符号表索引或更多机器级别?我希望从词法范围闭包中抛出一个错误,因为原来的s被删除了。新的s只是重复使用该名称,与原始s无关。

第三,s不使用匿名函数范围内的f(),这是否意味着词法范围确实在起作用?

2 个答案:

答案 0 :(得分:3)

  

首先,您可以关闭尚未定义的变量   ...如果使用词汇(静态)范围,那怎么可能?

参考hoisting

  

第二,删除原始s后,f()可以找到新的s。是否   这意味着闭包绑定到变量名而不是引用   或符号表索引或更多机器级别的东西?我会   期望从词汇范围闭包中抛出一个错误,因为   原来的是删除。新的只是重用名称而没有任何东西   与原版s有关。

没有新的,所有声明都被悬挂。最后只有一个。 吊装仍然适用。

  

和第三,匿名函数作用域内的s未被使用   f(),这是否意味着词汇范围确实在起作用?

是的,匿名函数中的s是本地的,在这种情况下,闭包是在全局s上形成的。

答案 1 :(得分:2)

此示例等同于

var s;
function f() { return s; } // works fine though no `s` is defined yet !

s=1;
f(); // 1

delete s;

s=2;
f(); // 2 

(function() {
var s=3;
f(); // 2 and not 3 which means lexical scoping is at play (?)
})();

Javascript变量声明被提升到其作用域的顶部,然后被声明。然后将它们定义为用户设置它们的位置。因此,您可以在函数范围内声明之前引用javascript变量。

另请注意,删除通常用于对象的属性,而不是使用var声明的对象。无论关闭如何,在这种情况下删除都没有效果。请参阅此处的小提琴:jsfiddle