在JavaScript中没有块级作用域的概念。这就意味着在块语句中定义的变量,实际上是在包含函数中而非语句中创建的。
<script> for(var i=0;i<5;i++) { } alert(i); </script>
就上面这个例子中,可以弹出i是5,因为for语句事实上是包含在window.onload= function(){}这个函数中,alert也在这个函数中。
而在java、c++中i只会在for循环的语句块中定义,循环一但结束,变量i就会被销毁。而在JavaScript中i是定义在xxx()中的活动对象,因此从他有定义开始,就可以在函数内部随处访问他。
<script> for(var i=0;i<5;i++) { } var i; alert(i); </script>
即使像上面那样错误的重新声明同一个变量,也不会改变他的值5。JavaScript从来不会告诉你是否多次声明了同一个变量。遇到这种情况,它只会对后面的声明视而不见,不过,他会执行后面声明中的变量初始化。上述代码如果改为var i=3;则最后alert出来的是3.
function outputNumbers(count){ (function () { for (var i=0; i < count; i++){ alert(i); } })(); alert(i); //导致一个错误! }
这个例子就是在for循环的外部定义了一个私有作用域,这样在匿名函数里面定义的变量执性完了就都会被销毁。这个匿名函数就是一个闭包。
这种技术经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数。
一般来说,我们都应该尽量少向全局作用域中添加变量和函数。在一个由很多开发人员共同参与的大型
应用程序中,过多的全局变量和函数很容易导致命名冲突。而通过创建私有作用域,每个开发人员既可
以使用自己的变量,又不必担心搞乱全局作用域。例如:
(function(){
var now = new Date();
if (now.getMonth() == 0 && now.getDate() == 1){
alert("Happy new year!");
}
})();
把这段代码放到全局作用域里面去,这样在一月一号的时候就会弹出...,但是如果不采用这种方式的话,那么就要再全局作用域里面声明一个变量now。
这种做法可以减少闭包占用的内存问题,因为没有指向匿名函数的引用。只要函
数执行完毕,就可以立即销毁其作用域链了。