码迷,mamicode.com
首页 > 编程语言 > 详细

JavaScript的闭包特性

时间:2014-12-09 23:07:18      阅读:326      评论:0      收藏:0      [点我收藏+]

标签:blog   http   io   ar   os   sp   java   strong   on   

 

       闭包是一个比较抽象的概念,尤其是对js新手来说。在这里,我就我个人的理解j简单谈一下:

     闭包:官方解释是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。然而,当我看到这个官方解释的时候顿时就觉得不一般,这个解释太学术了,没达到一定境界的人是理解不了其中深层次内涵的。为此,我们将举出实例来初步说明js中的闭包特性。在了解闭包特性之前,我们需要补充了解变量的作用域。

一、变量的作用域

       在JS当中一个变量的作用域(scope)是程序中定义这个变量的区域。变量分为两类:全局(global)变量和局部变量。其中全局变量的作用域是全局性的,即在JavaScript代码中,它处处都有定义。而在函数之内声明的变量,就只在函数体内部有定义。它们是局部变量,作用域是局部性的。函数的参数也是局部变量,它们只在函数体内部有定义。

       我们可以借助JavaScript的作用域链(scope chain)更好地了解变量的作用域。每个JavaScript执行环境都有一个和它关联在一起的作用域链。这个作用域链是一个对象列表或对象链。当JavaScript代码需要查询变量x(如下图)的值时(这个过程叫做变量解析(variable name resolution)),它就开始查看该链的第一个对象。如果那个对象有一个名为x的属性,那么就采用那个属性的值。如果第一个对象没有名为x的属性,JavaScript就会继续查询链中的第二个对象。如果第二个对象仍然没有名为x的属性,那么就继续查询下一个对象,以此类推。如果查询到最后(指顶层代码中)不存在这个属性,那么这个变量的值就是未定义的。

     bubuko.com,布布扣

例子1:js中的全局变量,结果为50       例子2:js中的局部变量,结果报错,原因就                                                              是函数中的局部变量在外部是不能被引用      

      bubuko.com,布布扣     bubuko.com,布布扣

      例子3:看看下面代码,初一看好像结果是50,但是结果确实undefinde,我们来解释说明下为什么是undefind----->

      作用域链图中很明确的表示出:在变量解析过程中首先查找局部的作用域,然后查找上层作用域。在例子1中的函数当中没有定义变量i,于是查找上层作用域(全局作用域),进而进行输出其值。但是在例子2中的函数内定义了变量i(无论是在alter之后还是之前定义变量,都认为在此作用域拥有变量i),于是不再向上层的作用域进行查找,直接输出i。然而在例子3中,函数内部依然定义了变量i,于是不会去查找全局作用于,然而不幸的是此时的局部变量i并没有赋值,所以输出的是undefined。

                               bubuko.com,布布扣

二、闭包的概念

    上面官方解释比较学术,我个人比较同意下面这个说法——>即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必需访问其外部函数的局部变量、参数以及其他内部函数。这些局部变量、参数和函数声明(最初时)的值是外部函数返回时的值,但也会受到内部函数的影响。-----个人理解就是:闭包是能够读取其他函数内部变量的函数,即在外面可以调用函数中的函数的变量,其实他就是将函数内外部连接起来的桥梁。

如下面例子4:

这段代码有以下两个特点:

     1、函数b嵌套在函数a内部;2、函数a返回函数b;

引用关系如下图:

 

          bubuko.com,布布扣

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

   当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个我们通常所谓的“闭包”。

 

      当函数b执行的时候亦会像以上步骤一样。因此,执行时b的作用域链包含了3个对象:b的活动对象、a的活动对象和window对象,如下图所示:

          bubuko.com,布布扣

如图所示,当在函数b中访问一个变量的时候,搜索顺序是:

  1. 先搜索自身的活动对象,如果存在则返回,如果不存在将继续搜索函数a的活动对象,依次查找,直到找到为止。
  2. 如果函数b存在prototype原型对象,则在查找完自身的活动对象后先查找自身的原型对象,再继续查找。这就是Javascript中的变量查找机制。
  3. 如果整个作用域链上都无法找到,则返回undefined。

三、闭包的用途及优势

(一)、用途

     1、闭包可以读取函数内部变量    2、将函数内部变量的值始终保存在内存中

例子5:

bubuko.com,布布扣

      这个例子中的result实际上就是闭包函数b,他一共运行两次,第一次值99,第二次值为100,这就说明i一直在内存中,而不是在第一次a函数调用之后就自动清除。另外还需注意iAdd=function(){i++;},这里iAdd是全局变量,且它的值为匿名函数,其实也是一个闭包。

(二)、优势

 

 1、保护函数内的变量安全。以最开始的例子为例,函数a中i只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。

 

 

 

 2、在内存中维持一个变量。依然如前例,由于闭包,函数a中i的一直存在于内存中,因此每次执行c(),都会给i自加1。

 

 3、通过保护变量的安全实现JS私有属性和私有方法(不能被外部访问)。

 

原文地址:http://my.oschina.net/longteng2013/blog/156782

JavaScript的闭包特性

标签:blog   http   io   ar   os   sp   java   strong   on   

原文地址:http://www.cnblogs.com/q460021417/p/4154340.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!