JS闭包的运用及匿名函数的作用

转载:https://blog.csdn.net/a250758092/article/details/52638209
配合上一篇js函数分类的博客

1:闭包的目的

闭包的目的就是为了变量私有制,如果学过其他语言可以联想到protected 这个关键词,就是防止其他对象直接访问私有的属性或成员方法/函数,而只能通过调用 含有私有变量的对象来处理这个变量。

2:闭包的问题根源

有时候,我们希望有一个全局变量,能够作为唯一标识去读取数据,但是全局变量都属于window对象,这就产生了一个问题,那就是这个变量能在任何情况下被调用,修改,导致稳健性不够高,维护方面也会产生很大的忧患。举个典型的例子:计时器;

var counter = 0;

function add() {
    counter += 1;
}
add();
add();
add();

counter作为计数器,每当我们调用add的时候我们都能正常计数,但是即使不调用add,而是直接counter+=1;计数器一样能够增加,这并不是我们想要的。

那么我们为何不把计数器写在函数内部呢?

function add() {
var counter = 0;
    counter += 1;
}
add();
add();
add();

此时我们发现,每次调用add函数,计数器都被重置了,这跟我们想要不同,那么如何处理这个问题,让计数器即可以作为“全局变量”一样去计数,又不至于直接通过增加计数器这个变量都能修改计数值?(其实它是局部变量而不是全局变量,只是因为它没有被释放而一直存在,而达到类似全局变量的效果而已,其本质就是变量私有制!)

3:内嵌函数

所有函数都能访问全局变量。

实际上,在 JavaScript 中,所有函数都能访问它们上一层的作用域。

JavaScript 支持嵌套函数。嵌套函数可以访问上一层的函数变量。

该实例中,内嵌函数 plus() 可以访问父函数的 counter 变量:

function add() {
    var counter = 0;
    function plus() {counter += 1;}
    plus();    
    return counter; 
}

如果我们能在外部访问 plus() 函数,这样就能解决计数器的困境。

但是我们同样需要确保 counter = 0 只执行一次。

解决方式就是闭包。

4:闭包写法

var add=(function(){
var counter=0;

return function(){//闭包
counter+=1;
}

})();

add();
add();//输出结果为2

解释:add绑定了一个匿名函数(匿名函数防止变量污染,同时也可以防止其他函数直接调用),这个匿名函数返回值是一个闭包,也就相当于add绑定了一个闭包,每次调用add函数,计数器counter都会+1,而因为子函数(闭包)的存在,导致父函数(创建counter变量的函数)也一直存在。counter的生命周期也就一直存在,其效果就是“全局变量”的效果,但是由于匿名函数的原因,我们无法通过直接访问counter实现增加计数器,因为counter是匿名函数的局部变量。然而这个局部变量却因为闭包的原因一直存在。这就是闭包的原理。

关于(function(){})();这种写法,意思是把函数作为表达式,加上后面的(),表示立即执行,要知道小括号的作用就是把括号里面的代码块分组并返回值,而包裹匿名函数,返回的就是一个Function对象,再加上一个(),就跟平常调用函数的形式一样。正如我们在看JQ插件的时候,其最基本的代码格式就是(function(){})();

5:变量污染

当存在多个JS文件的时候,特别是项目文件数量很庞大的时候,变量污染的几率会更高,所谓变量污染,就像a.js b.js两个文件都存在一个叫
clear的全局变量,那么window.clear既可以是a.js的变量,也可以是b.js的变量,其值甚至取决于你导入文件的顺序,一般这个变量会是最后导入的那个。

匿名函数(function(){})();把这些全局变量变成了局部变量,虽然防止了变量污染,但是又出现了另外一个问题,那就是“通信”问题。a.js b.js之间的变量无法相互访问,我们不可能又创建一个全局变量来通信,这就回到了起点。为了恢复通信而又能尽可能阻止变量污染,我们可以使用唯一的全局变量

var GLOBAL{}

通过自定义命名空间来区分,这些变量到底是哪些文件的
比如a.js 中 GLOBAL.A.a
b.js 中 GLOBAL.B.a

这样就可以区分开了,所以命名空间的书写规范,必须得有自己的一套标准。

猜你喜欢

转载自blog.csdn.net/banjing_1993/article/details/80996437