闭包到底有什么用

闭包到底有什么用?难道就是在外部访问内部函数吗?最关键最重要的用处在哪?

阅读 6.7k
5 个回答

一、匿名自执行函数

    var data={
        table"{},
        tree:{}
    };
    
    (function(dm){
         for(var i = 0; i < dm.table.rows; i++){    
           var row = dm.table.rows[i];    
           for(var j = 0; j < row.cells; i++){    
               drawCell(i, j);    
           }    
        }    
    })(data);

我们创建了一个匿名的函数,并立即执行,由于外部无法引用它内部的变量,因此在执行完后很快就会被释放,这种机制不会污染全局变量。
二、缓存
因为闭包不会释放外部的引用,所以可以实现缓存的功能。

    var CachedSearchBox = (function(){    
        var cache = {},    
        count = [];    
        return {    
           attachSearchBox : function(dsid){    
               if(dsid in cache){//如果结果在缓存中    
                  return cache[dsid];//直接返回缓存中的对象    
               }    
               var fsb = new uikit.webctrl.SearchBox(dsid);//新建    
               cache[dsid] = fsb;//更新缓存    
               if(count.length > 100){//保正缓存的大小<=100    
                  delete cache[count.shift()];    
               }    
               return fsb;          
           },    
 
           clearSearchBox : function(dsid){    
               if(dsid in cache){    
                  cache[dsid].clearSelection();      
               }    
           }    
        };    
    })();    
 
    CachedSearchBox.attachSearchBox("input1");
     

三、实现封装

    var person = function(){    
        //变量作用域为函数内部,外部无法访问    
        var name = "default";       
   
        return {    
           getName : function(){    
               return name;    
           },    
           setName : function(newName){    
               name = newName;    
           }    
        }    
    }();    
 
    print(person.name);//直接访问,结果为undefined    
    print(person.getName());    
    person.setName("abruzzi");    
    print(person.getName());    

    得到结果如下:  

    undefined  
    default  
    abruzzi  

四、实现对象

    function Person(){    
        var name = "default";       
   
        return {    
           getName : function(){    
               return name;    
           },    
           setName : function(newName){    
               name = newName;    
           }    
        }    
    };    
 
 
    var john = Person();    
    print(john.getName());    
    john.setName("john");    
    print(john.getName());    
 
    var jack = Person();    
    print(jack.getName());    
    jack.setName("jack");    
    print(jack.getName());    

    运行结果如下:  

    default  
    john  
    default  
    jack  

总结:可以访问父函数的作用域是它最重要的特性,它的应用都是基于这个特性而来,不存在最关键的应用场景,只能说上述几种比较常用而已。

我是来补楼的,第一,闭包的理论知识各种社区已经介绍的够多了;闭包的实际应用多的数不清,我挑一篇近几个月读到的百度fex上的一篇文章推荐给题主-《Node.js Web应用代码热更新的另类思路》

里面有这样一处闭包的妙用,当然,如果要一下子理解这里为什么这么用肯定是不现实的。
题主不妨借这个机会去阅读一下express中app.use源码,然后再回过来细细品味这处妙用,相信你会对闭包有更深入的理解。

// app.js
var express = require('express');
var fs = require('fs');
var app = express();

var router = require('./router.js');

app.use(function (req, res, next) {
    // 利用闭包的特性获取最新的router对象,避免app.use缓存router对象
    router(req, res, next);
});

app.listen(3000);

// 监听文件修改重新加载代码
fs.watch(require.resolve('./router.js'), function () {
    cleanCache(require.resolve('./router.js'));
    try {
        router = require('./router.js');
    } catch (ex) {
        console.error('module update failed');
    }
});

function cleanCache(modulePath) {
    require.cache[modulePath] = null;
}

闭包有很多好处
首先 可以让一个子函数 使用父函数的作用域
其次 可以实现封装 比如 我返回几个东西

return { 
    a : function(){
    },
    b : function(){
    }
}

还有很多 建议google baidu
楼下继续补充吧 哈哈

你的问题没有提到javascript,不过我看所有人回答都是js....姑且就当你是问js里的闭包吧(虽然这对于闭包理解是本末倒置的)

js本身设计上有些问题(作用域的问题),以至于为了创造出局部作用域的量, 必须使用function, 而嵌套使用function又会让内层可以捕捉外层的自由变量, 其实大量使用闭包方式只是为了补救一开始的语言的设计问题(补救封装性)

如果js有其他语言中的namespace的等价物, 有其他语言的多种作用域关键字(for,try,if....)组合, 用闭包的情况会少很多.

除了这种情况外(补救js面向对象系统的缺陷), 还有少数情况(否则像C#这类有完整全面面向对象系统的语言干嘛也要支持闭包)一般发生在函数式编程的上下文中(js也是支持函数式编程的,并非一定要oo), 这跟其他函数式语言的闭包(除了scheme)的情况一样.

scheme语言里说的闭包一般是另外一种完全不同的东西,是数学上抽象代数里的 "闭包性质", 指的是一个函数作用于集合里的若干元素,得到返回值依然在集合里.我猜你想问的不会是这个,所以不展开了.

好吧我错了, 你tag里有 javascript了...虽然标题和内容没有

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏