闭包
文章目录
1. 闭包的现象
当内部函数被保存到外部时,将会生成闭包。
闭包会导致原有作用域链不释放,造成内存泄露。
内存泄露可以理解为内存占用,泄露(占用)的越多,内存剩余的越少。与信息泄露无关。
由于内部函数的作用域链中仍然有对包含函数的引用,所以包含函数执行完后,其活动对象没有被销毁,但是包含函数执行上下文的作用域链会被销毁。
例子:
function a() {
function b() {
var bbb = 234;
document.write(aaa);
}
var aaa = 123;
return b;
}
var glob = 100;
var demo = a();
demo(); //123
1.全局预编译
GO{
glob : undefined,
demo : undefined,
a : function a() {
...
}
}
2.执行语句var glob = 100;
GO{
glob : 100,
demo : undefined,
a : function a() {
...
}
}
3.执行语句var demo = a();
3.1.预编译函数a
对象a的[[scope]]属性
scope chain | |
---|---|
0 | aAO |
1 | GO |
aAO{
aaa : undefined,
b : function b() {
...
}
}
3.2.执行函数a
aAO{
aaa : 123,
b : function b() {
...
}
}
3.3.函数a执行完成,return b
a对应的执行期上下文销毁。但是由于a的内部函数b被保存到了变量demo中,形成闭包。
4.执行demo()
执行函数b
bAO{
bbb : 234
}
执行函数b中的document.write(aaa);
b的[[scope]]属性是保留下来的,aaa的值将在b的作用域链中寻找,能够访问到aAO中的aaa,因此打印123。
例子:
function a() {
var num = 100;
function b() {
num ++;
console.log(num);
}
return b;
}
var demo = a();
demo(); //101
demo(); //102
2. 闭包的作用
2.1 实现公有变量
eg. 函数累加器(不依赖于外部变量,并且能反复执行的函数累加器)
//函数累加器
var count = 0;
function test() {
count ++;
console.log(count);
}
test(); //1
test(); //2
//但是这种方式依赖于外部变量
利用闭包
function add() {
var num = 0;
function a() {
console.log(++ num);
}
return a;
}
var myAdd = add();
myAdd(); //1
myAdd(); //2
2.2 可以做缓存(存储结构)
function test() {
var food = "apple";
var obj = {
eatFood : function () {
if(food != "") {
console.log("I am eating " + food);
food = "";
}else{
console.log("There is empty!")
}
},
pushFood : function (myFood) {
food = myFood;
}
}
return obj;
}
var person = test();
person.eatFood(); //I am eating apple
person.eatFood(); //There is empty!
person.pushFood("banana");
person.eatFood(); //I am eating banana
2.3 可以实现封装,属性私有化
2.4 模块化开发,防止污染全局变量
3. 闭包补充
3.1 立即执行函数解决闭包问题
function test(){
var arr = [];
for(var i = 0; i < 10; i ++) {
arr[i] = function () {
document.write(i + ' ');
}
}
return arr;
}
var myArr = test();
for(var j = 0; j < 10; j ++) {
mtArr[j] ();
}
//10 10 10 10 10 10 10 10 10 10
function test(){
var arr = [];
for(var i = 0; i < 10; i ++) {
(function (j) {
arr[j] = function () {
document.write(j + ' ');
}
} (i));
}
return arr;
}
var myArr = test();
for(var j = 0; j < 10; j ++) {
mtArr[j] ();
}
//0 1 2 3 4 5 6 7 8 9
3.2 没有return也能形成闭包
var demo;
function test() {
var abc = 123;
function a () {
console.log(abc);
}
demo = a;
}
test();
demo();