【javascript】理解闭包(Closure)

原创 2015年11月19日 15:42:07

闭包:有权访问另一个函数作用域中的变量的函数。
创建闭包的常用方式:就是在一个函数内部创建另外一个函数。

1.快速开始

这样所确实不好理解,现在举一个简单的例子,快速入门。

function a(){
    var i=0;
    function b(){
        alert(++i);
    }
    return b;
}

var c=a();
c();//1

这样在执行完var c=a( )后,变量c实际上是指向了函数b,再执行c( )后就会弹出一个窗口显示i的值(第一次为1)。这段代码其实就创建了一个闭包,为什么?因为函数a外的变量c引用了函数a内的函数b,就是说:
当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。


这个时候我们仍然不太清楚怎么回事。现在我们先不看原理,直接过来看看它的作用。

2.闭包的作用

一句话:闭包的活动对象(变量)会常驻内存
a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量

3.闭包的原理

这部分是最复杂的,先举一个例子来提出来几个概念。

参考 Javascript高级程序设计(第三版)

function compare(value1, value2){
    if (value1 < value2){
        return -1;
    } else if (value1 > value2){
        return 1;
    } else {
        return 0;
    }
}
var result = compare(5, 10);

当调用compare()时,会创建一个包含arguments、value1 和value2 的活动对象。全局执行环境的变量对象(包含result和compare)在compare()执行环境的作用域链中则处于第二位。
这里写图片描述
概念:
执行环境:当调用compare()函数的时候,会为函数创建一个执行环境,通过复制函数的[[Scope]]属性中的对象建立作用域链
作用域链:作用域链本质上是一个指向变量对象的指针列表,它只
引用但不实际包含变量对象。包含:全局变量的对象和compare()的活动对象。
一般来讲,当函数执行完毕后,局部活动对象就会被销毁,内存中仅保存全局作用域(全局执行环境的变量对象)。
但是,闭包又有所不同:

function createComparisonFunction(propertyName) {

    return function(object1, object2){
        var value1 = object1[propertyName];
        var value2 = object2[propertyName];
    if (value1 < value2){
        return -1;
    } else if (value1 > value2){
        return 1;
    } else {
        return 0;
    }
  };
}

当createComparisonFunction()函数返回后,其执行环境的作用域链会被销毁,但它的活动对象仍然会留在内存中(匿名函数的作用域链仍然在引用这个活动对象);直到匿名函数被销毁后,createComparisonFunction()的活动对象才会
被销毁

//创建函数
var compareNames = createComparisonFunction("name");
//调用函数
var result = compareNames({ name: "Nicholas" }, { name: "Greg" });
//解除对匿名函数的引用(以便释放内存)
compareNames = null;

闭包

4.闭包的用途

参考 http://blog.csdn.net/sunlylorn/article/details/6534610

4.1 匿名自执行函数

例子:UI初始化,只需要执行一次,其内部变量无需维护

var datamodel = {    
    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);    
       }    
    }    

    //build dm.tree      
})(datamodel); 

4.2 缓存

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"); 

这样,当我们第二次调用CachedSearchBox.attachSerachBox(“input1”)的时候,
我们就可以从缓存中取道该对象,而不用再去创建一个新的searchbox对象。

4.3 实现封装

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  
版权声明:本文为博主原创文章,转载请注明出处和原文链接。

PHP 闭包函数及Closure对象的总结

疑问如果你在理解闭包函数的时候觉得比较费解,不如放一放,问自己一个问题: 面向对象编程语言对代码的复用主要采用继承来实现,那面向函数的代码复用能力通过什么来实现呢?你可能第一时间想到的是 函数嵌套,...
  • zoujunjie202
  • zoujunjie202
  • 2016年08月18日 13:56
  • 2491

Java中的闭包(Closure)和回调

上网看了许多关于Java中的闭包(Closure)和回调的博文,总算是弄清晰了,再次写下自己的笔记   1、闭包 定义:闭包允许你将一些行为封装,将它像一个对象一样传来递去,而且它依然能够访问 到原来...
  • woailuo453786790
  • woailuo453786790
  • 2016年06月07日 22:09
  • 2003

PHP闭包(Closure)

匿名函数 提到闭包就不得不想起匿名函数,也叫闭包函数(closures),貌似PHP闭包实现主要就是靠它。声明一个匿名函数是这样: $func = function() { }; //带结束...
  • jinbiao520
  • jinbiao520
  • 2013年06月23日 17:16
  • 2106

Javascript中闭包(closure)的理解与浅析

最近在网上查阅了不少Javascript闭包(closure)相关的资料,写的大多是非常的学术和专业。对于初学者来说别说理解闭包了,就连文字叙述都很难看懂。撰写此文的目的就是用最通俗的文字揭开Java...
  • xingchengzh
  • xingchengzh
  • 2012年01月04日 22:43
  • 165

学习 JavaScript 最难点之二 -- 理解closure(闭包)

在理解闭包之前, 首先要清楚JS中的作用域只有2种: 全局作用域和方法作用域 全局作用域很好理解了, 方法作用域就是指一个 function 形成一个独立的作用域, 而且方法作用域还能够嵌套.与别的...
  • mimixiao345
  • mimixiao345
  • 2015年07月27日 22:20
  • 256

深入理解JavaScript闭包(closure) – Felix Woo

近在网上查阅了不少Javascript闭包(closure)相关的资料,写的大多是非常的学术和专业。对于初学者来说别说理解闭包了,就连文字叙述都很难看懂。撰写此文的目的就是用最通俗的文字揭开Javas...
  • willvc123
  • willvc123
  • 2011年02月28日 17:03
  • 408

Javascript中闭包(closure)的理解与浅析

转载: 最近在网上查阅了不少Javascript闭包(closure)相关的资料,写的大多是非常的学术和专业。对于初学者来说别说理解闭包了,就连文字叙述都很难看懂。撰写此文的目的就是...
  • yugongpeng_blog
  • yugongpeng_blog
  • 2014年10月31日 11:21
  • 231

学习 JavaScript 最难点之二 -- 理解closure(闭包)

说完原型后, 我们紧接着来理解什么是闭包. 闭包虽不是JS的特色功能, 但要理解还真要费那么点工夫. 在理解闭包之前, 首先要清楚JS中的作用域只有2种: 全局作用域和方法作用域 全局作...
  • linshichen
  • linshichen
  • 2016年05月27日 11:59
  • 295

深入理解Javascript闭包(closure)

导读:   最近在网上查阅了不少Javascript闭包(closure)相关的资料,写的大多是非常的学术和专业。对于初学者来说别说理解闭包了,就连文字叙述都很难看懂。撰写此文的目的就是用最通...
  • han8888
  • han8888
  • 2011年10月21日 17:10
  • 154

深入理解JavaScript闭包(closure)

深入理解JavaScript闭包(closure) 发表于: 14:48 | 分类: 开发技术 | 评论: 36 | 人气: 11,304 | 最近在网上查阅了不少Javascript闭...
  • lionzl
  • lionzl
  • 2011年08月24日 08:52
  • 320
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【javascript】理解闭包(Closure)
举报原因:
原因补充:

(最多只允许输入30个字)