在网上看到一篇很好的文章,就是就写了这篇翻译&杂谈。
在编程时你需要取得某些变量或者方法时才能继续你的开发工作,而程序编译器通常会将这些方法封装到一个个作用域。当你进入作用域,你才能取得该作用域的变量或方法。所以在某种意义上说,作用域(scope)非常重要。
在js中,所有的变量/方法都是对象,这当然也包括作用域。最全局的作用域就是window。以下这个小程序可以让你很清楚的看到这点:
<html>
<script>
var a="test a";
window.b="test b";
function c(){
alert("test c");
}
alert("a is:"+window.a);
alert("b is:"+window.b);
window.c();
</script>
</html>
js存在名为作用域链的东东(scope chain) ,假设scopeA定义在scopeB中,scopeB定义在window中,那么当你访问某个变量a的时候,js现在当前作用域寻找,如果没有找到就到上层作用域寻找,周而复始,最后在window进行查找,如果再查找不到,就抛出异常.
多数程序语言对于作用域和变量的实现都是这样子的。似乎不用特别考究。
奇特的是在js内,函数内部还可以嵌套函数,所以你一定要对上述作用域的概念了然于胸。例如下面的例子:
<html>
<script>
var A = new function(){
var a ="test a";
function change(){
alert(a);
a="value changed";
};
this.visible=function(){
alert(a);
}
}
A.visible();
A.change();
</script>
</html>
你可以看到,visible方法可以访问而change则不能。于是这种方式就模拟了某些“OO”语言如Java,C++的OO功能:数据封装。并且,上述代码是js中创建singleton对象的方式。
在上述代码中,change称为闭包(closure),因为它能够访问位于本作用域外的属性或方法。然而,恕我直言,这种函数能访问外层作用域的变量或函数的方式在C++或者Java中不是很平常的事情?为什么会有个专门的名词呢?我暂时没有弄清楚,或者以后会认真读读js规范:
Javascript's specification 很好的一篇文章:
Getting Funky With Scopes and Closures 当然还有
Douglas Crockford 的主页