原文链接:http://www.qdfuns.com/notes/17398/9b28ba7e036240b1252f1c82b9883d94.html
老姚说:
产生闭包的三个条件:
- 调用的函数是父级作用域内部声明的
- 调用的函数是在父级作用域之外进行调用
- 调用的函数内部使用了父级作用域的内部变量
闭包举例
1.作为函数返回结构的一部分
var fun = function() {
var x = 0;
return {
fn: function() {
alert(++x);
}
};
}
var r = fun();
r.fn();
r.fn();
r.fn是fun的内部函数(注意函数是引用类型的),调用是在fun的外部调用的。
2.赋给外部变量
var fun1;
var fun2 = function() {
var x = 0;
fun1 = function() {
alert(x);
}
}
fun2();
fun1();
其中fun1是个闭包,条件都满足。有疑问的地方可能是,是否内部声明的呢?是的,因为fun1是个函数,是fun2的内部函数。
3.异步操作,绑定到dom事件
var fun2 = function() {
var btn = document.querySelector("#myBtn");
var x;
btn.onclick = function() {
alert(x);
}
}
fun2();
主要看看是否是外部调用。是的。因为用户点击时触发事件,不是在fun2中内部调用的。
如果btn是外部声明的,跟情况2差不多。
4.异步操作,setTimeout或setInterval
var fun = function(x) {
setInterval(function() {
console.log(x++);
}, 3000)
}
fun(1);
setInterval第一个参数,是一个函数,此函数的执行必须是在全局调用的。因此是闭包。
5.异步操作,ajax请求回调
6.特权函数
var Person = function() {
this.sayName = function() {
alert(name);
}
var name = "laoyao";
}
var p = new Person();
p.sayName();
上面我故意把sayName和name写反的,没有问题的。
只要是闭包,使用的外部变量位置“在哪”都可以的。当然闭包不是本质原因,只要在函数调用之前就行了。而闭包是在外部调用的。
这里来说说它为啥是闭包呢?
p.sayName是个构造函数内部声明的匿名函数,没问题。
调用时也是在构造函数之外调用。
写到这里,回想当初写的第一篇文章说闭包是一个函数的返回值,并引用了函数内部变量。现在看来还是太年轻。让怨念先飞一会儿。
最后,再来一个更深层的例子。
var fun1 = function() {
var x = 1;
return function fun2() {
var y = 5;
return function fun3() {
alert("x=" + (++x) +";y=" +(++y));
}
}
}
var fun2 = fun1();
var fun3 = fun2();
fun3();
fun3();
fun2和fun3都是闭包。如果结合上面的几种情况,类似的例子能写出很多。