模仿块级作用域
由于JavaScript没有块级作用域的概念。这意味着在块语句中定义的变量,实际上是在包含函数中而非语句中创建的,
1 function outputNumbers(count){ 2 for(var i=0;i<count;i++){ 3 console.log(i); // 0 1 4 }6 alert(i); // 2 7 }
这个函数中定义了一个for循环,而变量i的初始值被设置为0.在Java C++等语言中,变量i只会在for循环的语句块中有定义,循环一旦结束,变量就会被销毁。
在JavaScript中,变量i是定义在outputNumbers()的活动对象中的,因此从它有定义开始,就可以在函数内随处访问它。即使像下面这样错误地重新声明同一个变量,也不会改变它的值。
1 function outputNumbers(count){ 2 for(var i=0;i<count;i++){ 3 console.log(i); // 0 1 4 } 5 var i; 6 alert(i); // 2 7 }
因为JavaScript 会对后续声明视而不见;通过闭包的方式来模仿块级作用域,来避免这样的问题。
1 function outputNumbers(count){ 2 (function(){ 3 for(var i=0;i<count;i++){ 4 console.log(i); // 0 1 5 } 6 })(); 7 var i; 8 alert(i); //undefind 9 10 } 11 outputNumbers(2);
这种有哪些优点:
如果希望定义一些私有变量的时候,可以使用这种方式来定义,在全局作用域中应用得比较都,一般用在外部函数中,这样避免往全局中添加过多的变量,函数。一般来说,我们应该尽量避免在全局作用域中过度添加变量,在大型中的项目中,过多的变量和函数容易导致命名冲突。这样的话,每个开发人员就可以定义自己的变量,又不会与全局变量影响。
1 (function(){ 2 var now = new Date(); 3 if(now.getMonth()==0 && now.getDate()==1){ 4 alert("Happy new year"); 5 } 6 })();
把上面代码放在全局作用域中,可以确定那一天是1月1日;如果到了就会像用户输出 Happy new year;
这种做法可以减少闭包占用的内存问题,因为没有指向匿名函数的引用,只要函数执行完成,就立即销毁其作用域链。