闭包不管在前端的面试和实际应用中都有着重要的分量.经过各个资料的查找,现在写下我对闭包的一些理解.
首先,要理解闭包之前,要先理解清楚作用域和作用域链,如果这个不清楚,对闭包的理解就会很差,鹦鹉学舌了.
一、什么是作用域和作用域链.
作用域:变量在声明它们的函数体以及这个函数体嵌套的任意函数体都是有定义的.
举个例子:
function func() {
console.log(num); //输出:undefined,而非报错,因为变量num在整个函数体内都是有定义的
var num = 1; //声明num 在整个函数体func内都有定义
console.log(num); //输出:1
}
func();
num这个变量在func()这个函数里的是有定义的.num在func这个函数定义时就确定了num的作用域范围,而不是在func函数执行是才确定的.(这个一定要搞清楚,搞清楚这个才能理解闭包.)
那什么是作用域链呢,那就是类似于原型链的东西.
func1(){
var a=1;
func2(){
var b=2
console.log(a);
console.log(b);
};
func2();
};
func1();
我们来看上面这个函数,func2执行时,打印出a和b,b在func2的作用域内,所以他会直接打印出2,但是a不在自己的作用域内,所以他会通过作用域链,往他的上一级作用域里去找这个值,然后找到了a的赋值,是1,然后打印出来。这就是一个简单的作用域链。
如果还没找到,就会一直往上找,直到找到window对象位置。
二、什么是闭包
好的,那我们简单的了解了下作用域和作用域链,现在看下闭包。
闭包就是能够读取其他函数内部变量的函数
func1(){
var a=1;
return func2(){
var b=2
console.log(a);
console.log(b);
};
};
var m=func1();
上面的代码,m被赋值了一个回调的函数func2.func2就是一个闭包。m通过func2获取到了a的值,a是func1的内部值。
三、闭包的实际使用场景
我们先说说闭包的缺点,曾经我一直想避开闭包的,因为他有如下的注意点,作为小萌新,我还是比较谨慎的
(1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
(2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
可是呢,既然出来了这个概念,而且闭包其实也在很多地方被使用的。比如大家最熟悉的jqery框架,它就是通过闭包封装相关的功能集。

以上代码的构造函数中定义了两个特权方法:getName()、setName(),这两个方法可以通过对象访问,而且都有权访问私有变量name,但是在Person构造函数外部,没有任何方法可以访问name。由于这两个方法是在函数内部定义的,因此作为闭包能够通过作用域链访问到name。
还有它可以控制setTimeOut的调用,大家可以看看相关文章,我也是感觉这段时间对闭包终于有点清晰的理解了,所以写篇文章纪念下。
本文围绕JavaScript闭包展开,先介绍了作用域和作用域链,指出变量作用域在函数定义时确定,作用域链用于查找变量。接着阐述闭包是能读取其他函数内部变量的函数。还提及闭包的缺点及解决方法,最后说明了闭包在jQuery框架、构造函数等场景的实际应用。
1350

被折叠的 条评论
为什么被折叠?



