`
zzsj123
  • 浏览: 43450 次
社区版块
存档分类
最新评论

关于变量作用域,闭包的详解

阅读更多
var add_the_handlers = function(nodes){
    var i;
    for (i = 0; i < nodes.length; i += 1){
      nodes[i].onclick = function(e){
        alert(i);
      }
    }
};//糟糕的代码

 

 

我们先看这个糟糕的列子!这是javascript精粹上面的一个例子,一开始很是迷惑找了半天也找不到答案,最后自己啃书算是明白了一点(只自己明白了,不知道对否。)

先说几个名词:变量对象,作用域,作用域链,函数执行环境

再说几个和变量有关的知识:变量值分为基本类型值和引用类型值,而基本类型的值的复制是直接拷贝副本,而引用类型只是拷贝地址。但是在给函数传参时,全部是按值传递的,就像基本类型值变量的复制一样。

 

 我们来说列子。

      当调用这个add_the_handlers函数时,把节点数组传递到这个函数执行环境中,这时的执行环境中有两个变量一个是I,另一个则是nodes.length,而这两个变量当add_the_handlers这个函数执行完毕,而且也没有函数或者其他变量引用这个两个值,他就会消失(这里是作用域的概念)。

 

      但是当进入for循环后,当I为0的时间给节点0绑定上这个事件函数,也就是function(e){ alert(i); }这段代码,这里你要注意哦!这段代码没有人去调用,所以他不会执行,直到你触发这个节点为0的事件后这段代码才调用。所以当I值为1的时间同样给节点为1的绑定上一样的函数。直到节点数组的值绑定完。

 

      这时这个add_the_handlers函数执行环境中的变量I值就变成了节点数目的值。但当我们去触发所有这些节点事件时,开始调用绑定的事件函数,而这个事件函数的执行环境中压根没有这个I变量值,他该怎么办,他根据作用域链的关系只有往上一级的执行环境寻找这个I的值。所以对于上级的执行环境也就是

add_the_handlers这个环境中的I值,有人在引用着他所以这个函数执行完毕I值不能消失而节点数可以消失,但是不能消失他保存在哪里了呢?实际上市保存在变量对象中(这个东西看不到,也不能调用),而这时的I值就是循环后的结果了,也就是节点数,所以当你不管点击那个节点弹出来的都是总节点的数目(也就是nodes.length的值)

 

 经过改良的列子

         var add_the = function (nodes){
            var helper = function (i){
              return function (e){
              alert(i);
              }
            }
              var i;
              for(i = 0; i < nodes.length; i +=1){
                 nodes[i].onclick = helper(i);
              }

         }

 

当调用函数时,初始I值,给第0个节点绑定上这个函数helper(i),而这个I值根据函数传参的原理,会有一个同样的I值进入到helper这个执行环境中,而这个环境中返回出来的一个函数,在引用着helper这个函数执行环境中的变量I(因为返回出来的函数他没有I那个变量,只能往上级执行环境查找这个值),所以这个I值不会消失。其他同理

 

 

总结:

     当一个函数内部被返回出来的函数,可以访问到他外部的函数执行环境中的变量或者对象,也就是说可以访问到他被创建时间的上下文环境,这就被称为闭包!我们这个例子中第二个例子helper()被称为闭包

  闭包的特性:

 

1,闭包外层是个函数.

2,闭包内部都有函数.

3,闭包会return内部函数.

4,闭包返回的函数内部不能有return.(因为这样就真的结束了)

5,执行闭包后,闭包内部变量会存在,而闭包内部函数的内部变量不会存在.

 

闭包的应用场景

1、保护函数内的变量安全。

2、在内存中维持一个变量。

 

分享到:
评论

相关推荐

    基于Python闭包及其作用域详解

    闭包和函数调用没多少相关,而是关于使用定义在其他作用域的变量 命名空间和作用域 我们把命名空间看做一个大型的字典类型(Dict),里面包含了所有变量的名字和值的映射关系。在 Python 中,作用域实际上可以看做是...

    javascript中的作用域和闭包详解

    JavaScript变量实际上只有两种作用域,全局变量和函数的内部变量。在函数内部任何一个地方定义的变量(var scope)其作用域都是整个函数体。 全局变量:指的是window对象下的对象属性。 作用域划分:基于上下文,以...

    【JavaScript源代码】详解JavaScript闭包问题.docx

     一、变量的作用域 在介绍闭包之前,我们先理解JavaScript的变量作用域。变量的作用域分为两种:全局变量和局部变量。 var n = 999; //全局变量 function f1() { a = 100; //在这里a也是全局变量 alert(n); }...

    JavaScript闭包详解1

    闭包 是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量闭包的缺点就是常驻内

    javascript作用域和闭包使用详解

    在一个函数中声明的变量以及该函数的参数享有同一个作用域,即函数作用域。一个简单的函数作用域的例子: 代码如下:function foo() { var bar = 1; { var bar = 2; } return bar; // 2} 不同于C等其它有块作用...

    JAVASCRIPT闭包详解

    而闭包工作机制的实现很大程度上有赖于标识符(或者说对象属性)解析过程中作用域的角色。 关于闭包,最 简单的描述就是 ECMAScript 允许使用内部函数--即函数定义和函数表达式位于另一个函数的函数体内

    深入Javascript函数、递归与闭包(执行环境、变量对象与作用域链)使用详解

    本篇文章对Javascript中函数、递归与闭包(执行环境、变量对象与作用域链)的使用进行了详细的分析介绍。需要的朋友参考下

    Python中的作用域规则详解

    Python是静态作用域语言,尽管它自身是一个动态语言。也就是说,在Python中变量的作用域是由它在源代码中的位置决定的,这与C有些相似,但是Python与C在...嵌套作用域的引入,本质上为Python实现了对闭包的支持,关于

    详解JavaScript作用域、作用域链和闭包的用法

    作用域是指可访问的变量和函数的集合。 作用域可分为全局作用域和局部作用域。 1.1 全局作用域 全局作用域是指最外层函数外面定义的变量和函数的集合。 换言之,这些最外层函数外面定义的变量和函数在任何地方都能...

    JavaScript中闭包的写法和作用详解

    闭包是有权访问另一个函数作用域的变量的函数。 简单的说,Javascript允许使用内部函数—即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、...

    JavaScript中闭包的详解

    好像有点清晰了,但是使用在它外面定义的变量是什么意思,我们先来看看变量作用域。 变量作用域 变量可分为全局变量和局部变量。全局变量的作用域就是全局性的,在 js 的任何地方都可以使用全局变量。在函数中使用 ...

    JS作用域链详解

    2、在某个方法函数的作用域中,所有代码执行完之后,该作用域被销毁,保存在其中的所有变量和函数定义也会随着被”销毁“,这就是局部作用域。但闭包不会销毁局部变量。 这里的销毁:是指下次再执行此函数的时候,...

    JavaScript作用域链实例详解

    对于JavaScript而言,理解作用域更加重要,因为在JavaScript中,作用域可以用来确定this的值,并且JavaScript有闭包,闭包是可以访问外部环境的作用域的。 每一个JavaScript的函数都是Function对象的一个实例,...

    JavaScript闭包和回调详解

     闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量。使用闭包有一个优点,也是它的缺点,就是可以把局部变量驻留在...

    JavaScript中最容易混淆的作用域、提升、闭包知识详解(推荐)

    就是作用域在一个“Function”里,属于这个函数的全部变量都可以在整个函数的范围内使用及复用。 function foo(a) { var b = 2; function bar() { // ... } var c = 3; } bar(); // 失败 console.log( a, b, c ); ...

    闭包以及闭包的应用详解

    理解闭包,首先的了解JavaScript的作用域的特点 javascript语言的特别之处就在于:函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。 注意点:在函数内部声明变量的时候,一定要使用var...

    Javascript闭包(Closure)详解

    要理解闭包,首先必须理解Javascript特殊的变量作用域。 变量的作用域无非就是两种:全局变量和局部变量。 Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。 var n=999; function f1(){  alert&#...

    实例详解Python装饰器与闭包

    要理解闭包,先要了解Python中的变量作用域规则。 变量作用域规则 首先,在函数中是能访问全局变量的: &gt;&gt;&gt; a = 'global var' &gt;&gt;&gt; def foo(): print(a) &gt;&gt;&gt; foo() global var 然后,在一个嵌套函数中,内层函数...

    基于Python函数的作用域规则和闭包(详解)

    作用域规则 命名空间是从名称到对象的映射,Python中主要是通过字典实现的,主要有以下几个命名空间: 内置命名空间,包含一些内置函数和内置异常的名称,在Python解释器启动时创建,一直保存到解释器退出。内置命名...

    js闭包用法实例详解

    本文实例讲述了js闭包用法。分享给大家供大家参考,具体如下: ...变量作用域 我们都非常的熟悉变量的作用域就分为:全局变量和局部变量。js中在函数的内部可以直接读取全局变量。 Js代码 var n=999; functi

Global site tag (gtag.js) - Google Analytics