Appearance
闭包
什么是闭包
有权访问另一个函数作用域中变量的函数,就叫做闭包。可见闭包跟函数作用域链息息相关。 闭包很常见,但请跟匿名函数区别开。
javascript
function fun1(){
var name = '这是名称'; // 这是fun1的一个局部变量
function fun2(){ // fun2是fun1的内部函数 且调用了fun1的name变量,这就是一个闭包
console.log(name); // 调用fun1的name变量
}
fun2();
}
fun1();
闭包的作用
- 可以访问函数作用域外的变量,将函数与其操作的属性关联起来-----对象的概念
闭包的缺点
- 因为闭包可访问另一个函数作用域中的变量,导致函数的变量一直存放在内存中,导致内存泄露,所以我们在使用闭包的时候记得手动去清除内存。
1. 私有属性方法
javascript
// 第一种方式
function People(name, age) {
this.name = name;
this.age = age;
}
People.prototype = {
getName: function() {
return this.name;
},
getAge: function() {
return this.age;
}
}
People.prototype.constructor = People;
var zhangsan = new People('张三', 26);
console.log(zhangsan.getName());
// 第二种
function People1(name, age) {
var obj = {
name: name,
age: age,
getName: function() { //这就是一个闭包 可以保存函数外的属性 name
return this.name;
},
getAge: function() {
return this.age;
}
}
return obj;
}
var zhangsan1 = new People1('张三', 26);
console.log(zhangsan1.getName());
2. 在循环中创建闭包 :一个常见错误
javascript
var obj = {};
for(var i=10;i>0;i--){
obj[i] = function(){
console.log(i);
}
}
for(var j=10;j>0;j--){
obj[j](); //我们发现不是我们需要的 10,9,8,.... 1,0,而是 0,0,0,0,0,0...,0
}
// 为什么 因为函数的内部作用域是执行的时候确定的而不是 定义的时候确定的。
// 所以当我们调用 obj[10]()的时候 上面的循环已经遍历完成 所以 执行的时候其访问上级作用域的i 其已经变成了 0; 所以输出 0 ,0,0,0,0.. 10次
var obj = {};
for(var i=10;i>0;i--){
obj[i] = function(){
console.log(i);
}
}
for(var i=10;i>0;i--){
obj[i](); //此时就是10,9,8,.... 1,0
}
// 如何修改
var obj = {};
for(var i=10;i>0;i--){
(obj[i] = function(){
console.log(i);
})()
}
for(var j=10;j>0;j--){
obj[j](); //10,9,8,.... 1
}
// 第二种方式
var obj = {};
for(var i=10;i>0;i--){
obj[i] = (function(i){
return function(){
console.log(i)
};
})(i)
}
for(var j=10;j>0;j--){
obj[j](); //10,9,8,.... 1
}