简单解释闭包就是能够读取其它函数内部变量的函数。它的两个最大用处:可以读取函数内部的变量;让这些变量的值始终保持在内存中。
js中变量作用域分为: 全局变量 和 局部变量,JS的特殊之处在于:每个函数都会创建一个新的作用域,函数内部可以读取外部变量,而函数外部无法读取内部变量。
创建:只要在一个函数中再定义一个函数,这个内部函数就是一个闭包。
function foo() {//这是普通内部函数访问外部变量。执行console.log()时,在bar作用域没找到a,去上一级foo作用域找到,所以输出2。
var a = 2;
function bar() {
console.log( a );
}
bar();
}
foo();//2
function foo() {//这是闭包,todo函数访问到了bar函数作用域变量a。执行 foo() 时,其实将函数 bar() 作为值引用类型传递给了 todo,当执行 todo() 时 等于执行了 bar()。
var a = 2;
function bar() {
console.log( a ); // 2
}
return bar;
}
var todo = foo();
todo(); // 2
闭包的常用例子:
for(var i = 0; i < 3; i++ ){//每隔一秒循环打印
(function(x){ setTimeout(function(){
console.log(x) },x*1000) })(i)
}
将变量始终保存在内存中:
function foo() {//函数bar被赋给了一个全局变量,这导致函数bar始终在内存中,而bar的存在依赖于foo,因此foo也始终在内存中。add是一个全局变量,它的值是一个匿名函数也是一个闭包。
var a = 2;
function bar() {
console.log( a ); // 2
}
add=function(){a+=1;}
return bar;
}
var todo = foo();
todo(); // 2
add();
todo();
闭包中使用this对象可能会导致一些问题。因为匿名函数的执行具有全局性,因此其this对象通常指向window。
var
name =
"The window"
;
var
object = {
name:
"My object"
,
getNameFun:
function
(){
return
function
(){
return
this
.name;
};
}
};
alert(object.getNameFun()());
//"The window"(在非严格模式下)
var
name =
"The window"
;
var
object = {
name:
"My object"
,
getNameFun:
function
(){
var
that =
this
;
return
function
(){
return
that.name;
};
}
};
alert(object.getNameFun()());
//“My object”
function
Cars(){
this
.name =
"Benz"
;
this
.color = [
"white"
,
"black"
];
}
Cars.prototype.sayColor =
function
(){
var
outer =
this
;
return
function
(){
return
outer.color
};
};
var
instance =
new
Cars();
console.log(instance.sayColor()())
function
Cars(){
this
.name =
"Benz"
;
this
.color = [
"white"
,
"black"
];
}
Cars.prototype.sayColor =
function
(){
var
outerColor =
this
.color;
//保存一个副本到变量中
return
function
(){
return
outerColor;
//应用这个副本
};
outColor =
null
;
//释放内存
};
var
instance =
new
Cars();
console.log(instance.sayColor()())