一,闭包
一句话: 闭包就是一个作用域链的问题,能够访问其它函数内部变量 的函数叫做闭包! 引用用阮一峰老师的一句话: 在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁 ! 下面来看下关于闭包的小栗子:
dom01
function fn() {
var a = 2;
function fx() {
console.log(a);
}
return fx;
}
var result = fn();
result(); // 2
1.函数fn()内部定义了一个局部变量a,和一个函数fx();
2.fn()的返回值是fx()这个函数;
3.当调用fn()函数时,fn()的返回值是fx()函数,然后定义一个变量result保存起来;
4.这时result是一个函数,result()就调用了这个函数;
5.函数result()发生调用被执行,就打印出2;
结论:函数fx就是闭包!
二,for循环+闭包
for循环就不必多说了,直接看dom!
dom02
for (var i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
dom02结果肯定是6 6 6 6 6了,这里也涉及到了同步和异步的问题:
1.每一次for循环都会产生一个异步任务定时器;
2.它会放在任务队列中等同步任务执行完后再去执行;
3.当i等于6时,i<=5不成立,跳出for循环;
4.此时i的值为6,有5个定时器就打印出5个6了!
dom03
for (let i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
dom03因为let具有块级作用域,每循环一次就会产生一个单独的作用域,所以打印出来就是1 2 3 4 5了!
dom04
for (var i = 1; i <= 5; i++) {
(function () {
var j = i;
setTimeout(function timer() {
console.log(j);
}, j * 1000);
})();
}
dom04就是一个闭包的栗子了,每循环一次i变量的值就会被保存起来,因为每次循环i的值都会被保留给下面定时器函数用,不会被垃圾机制回收,所以打印出来就是1 2 3 4 5了!
dom05
我们对dom04的栗子做了一下小小的改进:
for (var i = 1; i <= 5; i++) {
(function (i) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
})(i);
}
三.关于闭包的思考题
下面两个思考题都是摘自阮一峰老师的,如果你能做出来并讲解就能彻底明白闭包了!
dom06
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function () {
return function () {
return this.name;
};
}
};
alert(object.getNameFunc()());
dom06栗子中有一个情况需要考虑,就是this指向问题:
1.在object中getNameFunc这个函数中this是指向object的;
2.getNameFunc函数中返回值又是一个函数,它里面的this指向的是window;
3.当object.getNameFunc()调用时,它的返回值是function () { return this.name };
4.当object.getNameFunc()()调用时,它的返回值是this.name;
5.这时this.name指向的就是window.name,var name = "The Window"是定义的全局,所以object.getNameFunc()()就会弹出The Window;
dom07
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function () {
var that = this;
return function () {
return that.name;
};
}
};
alert(object.getNameFunc()());
dom07和dom06中有一个不同就是getNameFunc函数中,把this保存给了that!
1.当object.getNameFunc()()调用时,它的返回值是that.name;
2.前面this指的是object,而var that = this,故that.name就是My Object;
这时就形成了闭包!