yishuixs
2015-04-15 05:39
采纳率: 74.7%
浏览 1.8k

关于javascript闭包的一点疑问

闭包存储局部变量的机理是什么?它如何存储的?比如如下一个闭包

 function test(){
     var num = 10;
     return function(){
        num++;
        return num;
    };
 };
 var n = test();
 alert(n());    //返回11
 alert(n());    //返回12,实现了累加
 alert(n());    //继续累加

第二次alert(n())通过闭包实现了累加,但是这个局部变量num是如何存储在内存里的,以至于可以持续调用?机理是什么?局部变量不是当函数调用完后就销毁了吗

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

7条回答 默认 最新

  • danielinbiti 2015-04-15 05:46
    已采纳

    test函数的内部函数被赋予n这个全局变量,因为n内部含有test函数的局部变量num,所以test函数的num局部变量不会被释放。执行一次n,num就会在原来的基础上加1

    点赞 打赏 评论
  • 只要变量被其他地方引用到,是不是被释放的,你返回了匿名函数,函数引用到num变量,只有n存储的匿名函数句柄被销毁才会释放

    点赞 打赏 评论
  • oyljerry 2015-04-15 05:53

    你可以理解num为n的一个成员了,n存在,所以num就一直存在,没有被释放

    点赞 打赏 评论
  • blownewbee 2015-04-15 05:59

    num是属于test的,不是属于匿名函数的,它会被解释器传给匿名函数,但是它的生命周期是和test一样的。

    点赞 打赏 评论
  • 清水依恋成 2015-04-15 05:59

    javascript本身就是一门编译解释语言,而且是在浏览器上运行,属于二次解释语言,不能直接翻译成
    图片说明
    本身就是先执行一个函数,返回结果,然后被上层函数再次返回结果到外面。
    其实一开始执行的函数就是缺省函数,因为浏览器不必再分配一个方法名给它了,就是一块解释文本,告诉浏览器直接按缺省函数规定干好活就可以了。

    给你一个简单纯js代码,这个是基本的函数调用,也是最基础的语法了。
    function DeleteRouteTable(divId, riF, nameF, msgF){
    this.riField = riF;
    this.nameField = nameF;
    this.msgField = msgF;

        var div = document.getElementById(divId);
    
        this.table = document.createElement("TABLE");
        div.appendChild(this.table);
        this.table.width = "100%";
        this.table.cellSpacing = 0;
        this.table.border = 1;
    
        this.tbody = document.createElement("TBODY");
        this.table.appendChild(this.tbody);
    
        this.arrayRI = new Array();
    }
    
    DeleteRouteTable.prototype.setValue = function(array){
        while(this.table.rows.length>0){
            this.table.deleteRow(0);
        }
    
        for(var i=0;i<array.length;i++){
            var item = array[i];
            this.arrayRI.push(item[this.riField]);
    
            var tr = document.createElement("TR");
            this.tbody.appendChild(tr);
    
            var tdRi = this.createTD(item[this.riField], 100, 2, "black");
            tr.appendChild(tdRi);
            var tdName = this.createTD(item[this.nameField], 100, 2, "black");
            tr.appendChild(tdName);
            var tdMsg = this.createTD(item[this.msgField], -1, 2, "red");
            tr.appendChild(tdMsg);
        }
    };
    
    DeleteRouteTable.prototype.createTD = function(value, width, fontSize, fontColor){
        var td = document.createElement("TD");
        if(width!=-1){
            td.width = width;
        }       
    
        var font = document.createElement("FONT");
        td.appendChild(font);
    
        font.size = fontSize;
        font.color = fontColor;
        font.innerText = value;
    
        return td;
    };
    
    点赞 打赏 评论
  • blownewbee 2015-04-15 06:01

    alert(test()());
    这样每次都是11了。

    点赞 打赏 评论
  • lhl_lqc 2015-04-15 06:15

    闭包里引用了外部的变量,那这个变量就会成为闭包函数作用域的一部分,闭包不回收变量也就不会被回收,因此闭包很多可能造成内存泄露。
    你这个例子,如果把里面的闭包函数换成num++,根据常识也应该知道每次调用test函数时都是一次全新的调用,每次调用输出的都是一样的值。
    因为num是test函数内部的一个局部变量,每次调用时都会被重新定义,重新赋值,使用完然后销毁。如果加上闭包函数,在里面调用num++,
    上面已经说了,num没有被销毁,加一次是1,再加一次自然就变成了2,如此累加。

    点赞 打赏 评论

相关推荐 更多相似问题