JavaScript缺乏块级作用域,变量易污染全局。本文介绍利用匿名函数模仿块级作用域的方法:通过立即调用的函数表达式(IIFE)创建私有作用域,使内部变量在函数执行后销毁,从而减少全局变量和闭包内存占用,优化代码结构。
JavaScript匿名函数定义与分类
匿名函数
函数作为JavaScript中最灵活的对象类型,本文主要聚焦于其匿名函数的具体应用。
所谓匿名函数,即指没有显式函数名的函数定义。
在深入探讨之前,简要回顾函数的三种常见定义方式。
第一种方式:这是最为常规和常见的定义方法。
function double(x){
return 2 * x;
}
第二种方式:利用Function构造函数,将参数列表和函数体作为字符串传入。这种方式不仅书写不便,且存在安全隐患,因此不建议使用。
var double = new Function('x', 'return 2 * x;');
第三种方式:
var double = function(x) { return 2* x; }
需注意,“=”右侧的函数本身是一个匿名函数。在创建该函数后,将其引用赋值给变量square。
JavaScript作用域机制解析
JavaScript语言本身并不具备块级作用域的概念。这意味着,在块级语句(如if或for循环)中定义的变量,实际上是被创建在包含该语句的函数(或全局)活动对象中,而非语句块内部。
function outputNumber(count){
for(var i=0;i<1000;i++){
alert(i);
}
alert(i); //count
}
在Java、C#等语言中,变量i的作用域仅限于for循环语句内部,循环结束后i即被销毁。然而在JavaScript中,变量i定义在outputNumber()函数的活动对象中,因此从定义开始即可在函数内部访问。即使再次声明同名变量,也不会改变其原有值或作用域范围。
function outputNumber(count){
for(var i=0;i<1000;i++){
alert(i);
}
var i; //重新声明变量
alert(i); //count
}
利用匿名函数模仿块级作用域
利用匿名函数可以模仿块级作用域,从而避免上述变量污染问题。用作块级作用域(也称私有作用域)的匿名函数语法如下:
(function(){
//这是块级作用域
})()
上述代码定义并调用了一个匿名函数。将函数声明包裹在小括号内,表明这是一个函数表达式。紧随其后的另一对小括号表示立即执行该函数。无论何时,只要临时需要一些局部变量,都可以使用这种私有作用域,例如:
function outputNumber(count){
(function(){
for(var i=0;i<1000;i++){
alert(i);
})();
alert(i); //导致一个错误
}
这样,我们在for循环外部插入了一个私有作用域。在匿名函数内部定义的变量,会在函数执行结束时被自动销毁。
这种技术常用于全局作用域中的函数外部,旨在限制向全局作用域中添加过多的变量和函数。
一般而言,应尽量减少向全局作用域中添加变量和函数,以保持全局环境的整洁。
这种做法有助于减少闭包占用内存的问题。由于没有指向匿名函数的持久引用,只要函数执行完毕,其作用域链即可立即销毁,从而释放内存。