关闭

javascript闭包

标签: javascript闭包
174人阅读 评论(0) 收藏 举报
分类:

浅谈闭包

 

想弄清闭包,我们首先得知道我们为啥要用到闭包呢,我们想要在一个函数内部取到函数外部的变量,或者调用函数外部的方法都是很容易的,因为javascript查找变量或方法都是逆着作用域链向上查找的,但是我们现在有了这样一个需求:我们想在函数外面取到函数内部一个临时变量的值,这样的需求使得我们违背了javascript的基本原则。而闭包恰好帮助我们解决了这个问题。

 

接下来我们看一个例子:

function setName(){
    var name="CSDN";
    function getName(){
        return name;
    }
}

 

getName函数是不是取到了setName函数内部的临时变量,这确实是的。

 

我们再看一个经典的错误例子:

我们想在数组的每项上绑定一个函数,希望他执行的时候能一次打印0,1,2,,,9;

但是发现,他只能打印1010

function consoles(){
    var arr=[];
    for(var i=0;i<10;i++){
        arr[i]=function(){
            console.log(i);
        }
    }
    return arr;
}

var arr=consoles();
for(var j=0;j<10;j++){
    arr[j]();
}

 

 

 

 

 

我们稍微把代码改一下:

 

 

 

function consoles(){
    var arr=[];
    for(var i=0;i<10;i++){
        arr[i]=(function(num){
            return function(){
                console.log(num);}
        })(i)
    }
    return arr;
}

var arr=consoles();
for(var j=0;j<10;j++){
    arr[j]();
}

 

我们使得一个匿名函数自执行,返回一个函数给数组各项,这样就行了。

弄懂这两个基本可以理解闭包了,在讲这两个例子之前咋们还得说一个例子做一个铺垫~~(不要嫌我啰嗦啦。。。)

 

function setName(){
    var name="CSDN";
    function getName(){
        return name;
    }
}

 

这就是文章开头写的那个例子,如果我们直接在setName外面调用getName肯定是得不到name值的,但是如果我们这样稍稍变化一下呢,

function setName(){
    var name="CSDN";
    return function (){
        alert(name);
    }
}
var get=setName();
get();

 

我们在setName内部返回一个函数,在函数外部用get变量接受,继续调用get函数,打印CSDN,这样为什么就行了呢?原因就是我们返回的函数可能会被再次调用,所以他用到的setName的局部变量不会在setName调用完毕之后就被gc回收,局部变量name会常驻内存,当我们再次调用get函数即setName返回的函数,就会弹出”CSDN”;

我们这时候再回头看一下那个经典例子:

function consoles(){
    var arr=[];
    for(var i=0;i<10;i++){
        arr[i]=function(){
            console.log(i);
        }
    }
    return arr;
}

 

为什么我们循环执for(j=0;j<10;j++){

arr[j]();

}

会打印10 10 呢?

我们在这个函数中返回的是一个数组,每个项都存着一个函数,这跟我们之前直接返回一个函数,再调用,是不是大同小异啊,我们返回的数组中的10个函数有可能会被再次调用,所以我们在consoles函数中定义的局部变量i,是不会在consoles执行完毕就被垃圾回收机制回收,在循环结束i的值为10,这个值会一直保存在内存中,当arr[j]()调用时就会寻找到这个i值,这样就会打印1010,如果我们在内部循环结束重新给i赋值1,这样就会打印10 1了,现在清楚点了吧~~

 

那为什么我们这样改一下就行了呢?

function consoles(){
    var arr=[];
    for(var i=0;i<10;i++){
        arr[i]=(function(num){
            return function(){
                console.log(num);}
        })(i)
    }
    return arr;
}

var arr=consoles();
for(var j=0;j<10;j++){
    arr[j]();
}

 

我们使用匿名函数的自执行,把i值传入匿名函数内部,我们返回的是表达式!这个表达式当然能够接收到我们传入的i值即num

 

闭包就是能够访问函数内部变量的函数,闭包有两个特点1他能够访问函数内部的变量2、她能让函数内部的变量常驻内存

正是由于这样我们才可以访问函数的局部变量,当闭包执行的时候,包含他的函数的执行环境会加入到闭包的执行环境中去,这个才是关键。。。。闭包越多消耗的内存就越多,因为她要保存包围他的函数的执行环境,所以不用闭包就要手动释放,通知垃圾回收机制回收内存,以免造成内存泄露。

真正要搞明白闭包,还是要清楚作用域链和函数的执行环境~~打好基础很重要~这样理解起来就会轻松一点了~~

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:3568次
    • 积分:140
    • 等级:
    • 排名:千里之外
    • 原创:10篇
    • 转载:1篇
    • 译文:0篇
    • 评论:1条
    分享
    文章分类
    最新评论