闭包的深入理解
分享原因:在逛博客的时候,看到了有关闭包的问题,不是特别理解,然后查找了相关的文章。
1 | var n = 1; |
闭包是函数和声明该函数的词法环境的组合。
理解js变量的作用域
访问规则:
i) 函数内部可以直接读取全局变量
1
2
3
4
5
6
7var n=999;
function f1(){
alert(n);
}
f1(); // 999ii) 在函数外部无法读取函数内的局部变量
1
2
3
4
5function f1(){
var n=999;
}
alert(n); // Uncaught ReferenceError: n is not definediii) 内部函数可以访问外部函数的变量
1
2
3
4
5
6
7function f1(){
var n=999;
(function f2(){
alert(n);
})();
}
f1();//999如何实现从外部读取局部变量
js链式作用域结构:父对象的所有变量,对子对象都是可见的,反之则不成立。
1
2
3
4
5
6
7
8
9function fun1(){
var n=999;
function fun2(){
alert(n);
}
return fun2;
}
var result=fun1();
result(); // 999闭包的概念
理解上,闭包就是能够读取其他函数内部变量的函数,将函数内部和函数外部连接起来的一座桥梁;但是事实上闭包不是一个函数,而是函数和声明该函数的词法环境的组合,这个环境包含了这个闭包创建时所能访问的所有局部变量。
闭包的用途
产生条件:
- 一个函数,里面有一些变量和另一个函数
- 外部函数里面的函数使用了外部函数的变量
- 外部函数最后把它里面的那个函数用return抛出去
作用:
- 在函数外部可以读取函数内部的变量
- 让这些变量的值始终保持在内存中
注意:
- 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,可能导致内存泄露。解决方法是,在退出函数之前,将不需要的局部变量赋值为null。
- 闭包会在父函数外部改变父函数内部变量的值。如果你把父函数当作对象使用,把闭包当作它的公用方法,把内部变量当作它的私有属性,这时一定要注意,不要随便改变父函数内部变量的值。
- 当定义一个函数时,它实际上保存一个作用域链。当调用这个函数时,它创建一个新的对象来存储它的局部变量,并将这个对象添加至保存的那个作用域链上,同时创建一个新的更长的表示函数调用作用域的“链”。对于嵌套函数来讲,每次调用外部函数时,内部函数又会重新定义一遍。因为每次调用外部函数的时候,作用域链都是不同的。内部函数在每次定义的时候都有微妙的差别——在每次调用外部函数时,内部函数的代码都是相同的,但是关联这段代码的作用域链不相同,用闭包概念来说,也就是产生了新的闭包。