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

相关文章推荐

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

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

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

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

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

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

JavaScript--闭包(closure)理解

JavaScript–闭包理解学习JavaScript,肯定会接触到闭包。 如果是刚接触js的,往往难以清楚理解。闭包是什么函数对象通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内...

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

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

深入理解Javascript闭包(closure)

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

深入理解JavaScript闭包(closure)

深入理解JavaScript闭包(closure) 发表于: 14:48 | 分类: 开发技术 | 评论: 36 | 人气: 11,304 | 最近在网上查阅了不少Javascript闭...
  • lionzl
  • lionzl
  • 2011年08月24日 08:52
  • 310

JavaScript之闭包closure

1.什么是闭包字面理解:闭:关闭,封闭的意思,对外界不开放的。包:包装起来,包裹起来 我们都知道内层的作用域可以访问外层的作用域,但是反过来不行,但是有的时候,我们确实需要访问一个封闭空间中的数据,...

史上最详细的javascript闭包(Closure)说明

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。很早就接触过闭包这个概念了,但是一直糊里糊涂的,没有能够弄明白JavaScript的闭包到底是什...

javascript_closure闭包--1

如何理解javascript closure ?   接触过javascript的人应该听过闭包(closure),有一种...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【javascript】理解闭包(Closure)
举报原因:
原因补充:

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