JavaScript中私有作用域的使用

本文探讨了JavaScript中块级作用域的缺失及其对变量管理的影响,并介绍了如何利用匿名自执行函数实现私有作用域,以此减少全局污染并提高代码的可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们知道,JavaScript中是没有块级作用域的。也就是说,在块语句中定义的变量,实际上是在外部函数中而非在语句中创建的。如下:

function outNumber (count) {
    for (var i = 0; i < count; i ++) {
        alert(i);
    }
    alert(i);
}

outNumber(5); //5

以上代码会弹出"0"到"5'的数,实则在for循环中,只会弹出"0"到"4"的数,而"5"这个数字是在外部函数即outNumber中弹出的。变量i的值自增到"5"后,会跳出循环,最后i的值就是"5",并由外部函数弹出这个值。

在C、JAVA或类C的语言中,变量i只会在for循环中有定义,一旦循环语句结束,变量i也会被销毁。但是在JavaScript中,变量i是定义在外部函数outNumber()的活动对象中的,因此从它被定义开始,就可以在函数体内部随处访问它了,即使像下面重新声明该变量一样。

function outNumber (count) {
    for (var i = 0; i < count; i ++) {
        alert(i);
    }
    var i; //重新声明此变量
    alert(i); //弹出变量i最后的值
}

outNumber(5); //5

即使这样,也会像上例一样弹出结果。像这样重新声明变量,它只会忽略最后的声明。

注意:这只是重新声明了这个变量,并未赋值。如果重新声明并赋值的话,就会有不同的结果了

function outNumber (count) {
    for (var i = 0; i < count; i ++) {
        alert(i);
    }
    var i = 6;
    alert(i);
}

outNumber(5); //6

像这样,for循环中会弹出"0"到"4"的数。而outNumber函数中会弹出"6"数字,因为此时重新定义和初始化了变量i,相当于"var i = 6"覆盖了"var i =5",因此,最后弹出的是"6"。



举例上述一些例子只是说明:块语句中定义的变量,不仅可以在块语句中访问,也可以在外部函数(包含函数)访问到,而在实际开发中,我们不希望在包含函数中能访问该变量。因为解决的方法就是:



使用块级作用域(私有作用域)的匿名函数来表示。

(functin () {
    //这里表示块级作用域;
})();

以上代码定义并立即调用了一个匿名函数。将函数定义在一个圆括号里,实际上它就是一个函数表达式。后面紧跟着的圆括号,表示调用它。



我们知道,声明一个函数有两种方法:


1、使用关键字function后跟构造器的方法创建一个函数。

function func (a, b, c...) {
    //这里是函数体
}

func();//调用这个函数



2、使用函数表达式的方式创建函数:将一个匿名函数赋值给一个变量。

var func = function (a, b, c...) {
    //这里是块级作用域
};

func();//调用这个函数



这里第二种方法创建的函数,是先创建一个匿名函数,并把这个匿名函数赋值给一个变量,调用函数的方式就是这个变量名后跟一个圆括号。这里,"func()"的这种方式我们是否可以看作是:

function (a, b, c...) {
    //这里是块级作用域
}();


但这样是会出错的,因为JavaScript将function关键字当作一个函数声明的开始,而函数声明后面是不能带圆括号的

我们知道一个函数表达式后面是可以跟圆括号的,就是像"func();"这样,那么将函数声明转换成函数表达式,就是在匿名函数上加上圆括号

(function (a, b, c...) {
    //这里是块级作用域
})();




无论在任何地方,只要是临时需要一个变量,就可以使用私有作用域,这样,变个变量就不会影响全局作用域了

function outNumber (count) {
    (function () { //临时需要一个变量i创建for循环
        for (var i = 0; i < count; i ++) {
            alert(i);
        }
    })();
    alert(i); //出错,这里的变量i未声明。
}

outNumber(5);


如上,在for循环外部插入一个匿名函数。在匿名函数中定义的变量,都会在匿名函数执行结束后被销毁。因此,变量i只能在for循环中使用,使用后被销毁。在私有作用域中能访问到参数count,是因为匿名函数是一个闭包,闭包能访问包含函数作用域中的所有变量。



私有作用域这种技术通常是在全局作用域上的函数外部使用,从而限制向全局作用域中过多的添加全局变量和函数。在实际开发中,我们应当尽量减少向全局作用域下添加过多的全局变量和函数,不然会形成内存泄漏的

在实际开发中,很多时候一个项目是由多个开发人员完成的,每个开发人员做的程序实现的功能不同,那么可能会需要多个变量,过多的全局变量和函数会导致命名冲突等问题。如果此时使用私有作用域,每个开发人员不仅有自己的变量,也不用担心搞乱全局作用域了。

(function () {
    var nTime = new Date();

    if (nTim.getMonth == 0 && nTime.getDate == 1) {
        alert("Happy new Year!!!");
    }
})();


以上代码功能就是判断当前时间是否是1月1日,如果是就输出祝福语。这个功能只是一个程序中小功能之一,函数调用执行后,局部变量nTime就会被销毁,腾出所占用的内存空间。当一个程序有多个小功能时,每个功能都会有自己的局部变量,执行完成后又被解除、释放其所占用空间,避免了内存泄漏。


通过以上的例子说明:使用私有作用域的技术可以减少闭包所占用的空间,因为没有指向匿名函数的引用当函数自调用执行完成后,马上销毁其作用域链了。还可以限制了向全局作用域中添加全局变量和函数,减少内存的占用率
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值