关于JavaScript中的闭包的疑问

一.到底什么是闭包?

是只要是函数嵌套函数,不管是被嵌套函数是否引用了外部函数的局部变量就是闭包,还是内部函数必须return出去之后才形成闭包?

1.第一个例子


 // #1
 function outer(a,b){
    var c = 999;
    
    function inner(){
     
       console.log(a,b,c);
    
    }
    
    inner(); // 直接调用了内部函数,并没有return出去,这是闭包么?
    
 }

/*----------------------分割线----------------------------*/

 // #2
 function outer(a,b){
    var c = 999;
    
    // 这种情况下,inner没有引用外部outer的变量
    function inner(){
       var d = 2;
       var e = 3;
       console.log(d+e);
    
    }
    
    inner(); // 直接调用了内部函数,并没有return出去,这是闭包么?
    
 }


/*----------------------分割线----------------------------*/

 // #3
 function outer(a,b){
    var c = 999;
    
    // 这种情况下,传入的str如果是变量名的话,就会引用outer内的变量
    function inner(str){
       console.log(eval(str));
    }
    
    return inner; 
    
 }
 var inner = outer(1,2);
 inner("a"); // 1
 inner("b"); // 2
 inner("c"); // 999

如果只要是函数嵌套函数就是闭包的话,那么如果没有return inner出去的话,也就不会出现在外面引用outer函数的局部变量了(#2),那么outer函数执行过后,即使outer内部的局部变量存在于内存中,也没有程序会访问到了,那么,GC会销毁outer内部的局部变量么?但是#3这种情况下,inner虽然没有显式地调用outer的局部函数,但是存在这种可能性,例如inner("a") 会访问outer的局部函数a,那么显然这种情况下,GC肯定不会销毁outer。。

哎呀,反正是很迷惑,请各位大牛给个醍醐灌顶的感觉吧???

2.第二个例子


 function outer(a,b){
    var c = 999;
    
    function inner(){
     
       console.log(a,b,c);
    
    }
    
    return inner; // 把内部函数return出去,就形成了闭包,这点儿我肯定
    
 }

二.使用闭包有什么好处?是怎么造成内存泄漏的?

阅读 4.6k
3 个回答

我们通常所说的闭包(之所以说“通常”,是因为从某种意义上来说,js中所有的函数都是闭包 —— 因为函数内部能够访问到外部的变量。但我们只关心下面所说的“闭包”),它的形成有两个要素:

  1. 闭包引用外部函数变量对象中的值;

  2. 在外部函数的外部调用闭包。

理解闭包的关键在于:外部函数调用之后其变量对象本应该被销毁,但闭包的存在使我们仍然可以访问外部函数的变量对象。

闭包闭包!了解更多

你可以这么认为,所有程序分配的变量都是不会回收的,所以只要你能想办法访问到就可以,不用去关心GC。GC设计的目的就是回收那些你绝对不用的内存。既然如此我们为什么要当作GC是存在的呢,在我们编程的时候即使当作GC是不存在的,对我们也没有什么影响。

闭包的可以实现类似私有成员的变量。
闭包可以防止变量名污染全局变量空间,就是说可以在一定程度上防止变量重名的问题。

内存泄漏:这个到不至于,这个在js里的意思是,使用闭包的时候特别容易不小心创建了过多的变量(而GC又无法回收),然后就导致内存耗尽。

题主通篇没有提作用域这个关键词。
理解闭包,先把作用域这块好好理解下。
a嵌套b,
a的作用域包含了b的作用域
b就可以引用a里的内部变量
但是a不能引用b里边的内部变量

闭包就是能够读取其他函数内部变量的函数。
所以闭包并不是像你说的由什么return 去触发的。
b在创建的时候,就有了可以使用a作用域的变量的权力
b这时候就是个闭包,也可以把闭包理解为‘定义在一个函数内部的函数,它是将函数内部和函数外部连接起来的一座桥梁’

闭包的好处,显而易见,比如创建个对象,可以封装一些特权方法访问私有属性。
也可以创建内部变量,不能在外部进行随意更改。

内存泄露问题,我理解不深,随便说两句,抛砖引玉
如果闭包也就是现在的b,b引用了a的内部变量的话。
如果需求需要b一直存在,也就导致a的内存也一直存在不会被回收,所以存在内存泄漏问题。
书上好像有过一个例子,内存泄露的情况:

function handel(){
    var dom = $('div');
    dom.click(function(){
        alert(dom.id)
    })
}

改成这种,就不会内存泄露

function handel(){
    var dom = $('div');
    var id = dom.id;
    dom.click(function(){
        alert(id)
    })
    dom = null;
}
推荐问题
宣传栏