Skip to content

闭包

什么是闭包

有权访问另一个函数作用域中变量的函数,就叫做闭包。可见闭包跟函数作用域链息息相关。 闭包很常见,但请跟匿名函数区别开。

javascript

function fun1(){
    var name = '这是名称';    // 这是fun1的一个局部变量
    function fun2(){          // fun2是fun1的内部函数 且调用了fun1的name变量,这就是一个闭包
        console.log(name);    // 调用fun1的name变量
    }
    fun2();
}
fun1();

闭包的作用

  1. 可以访问函数作用域外的变量,将函数与其操作的属性关联起来-----对象的概念

闭包的缺点

  1. 因为闭包可访问另一个函数作用域中的变量,导致函数的变量一直存放在内存中,导致内存泄露,所以我们在使用闭包的时候记得手动去清除内存。

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
}