var f = function( ) {
    var x = 1
    function fo() {
      console.log( x++ )
    }
      return fo
  }
  var fn = f()
  fn()              //  1
  fn()              //  2
 
  以上代码实现了一个简单的闭包,每次执行 fn 其内部变量 x 都会实现自增。
  
  闭包用一种巧妙的方式将原本互不敢干的作用域联合了起来,我在之前的文章 JavaScript之引用函数调用与直接调用的区别  说到作用域只有在代码块执行的时候才会产生,还有一点没有提到:作用域所占的内存是如何回收的,以及何时释放。
 
  闭包一直饱受诟病,下面具体为大家分析下我的观点:
  
  事实上,函数体包裹的每块代码在每次执行都会新产生一个作用域,然后在函数体执行完后被释放,我们平时在执行这一个过程的时候常常忽略了这样一个事实,所以在接触到闭包这些概念的时候短时间会无法接受。当然,如果你琢磨透了的话,并没有什么难理解的,比如函数体内定义了一个变量 x = 1,每次你调用这个函数,在其内部所引用的 x 值都是1,这意味着这个变量在上次函数体被执行完后就释放了,一个独立的作用域被执行完后就会被销毁。
 
  搞明白了上面这点,也就不难理解上面的代码,如果将函数体从一个函数内发送出去,那么就意味这此函数的作用域发射到了其上级作用域内,即两个作用域联合了起来,融合到一起了,这时候JavaScript再想销毁这个作用域就会连同 window 这个作用域一起销毁,显然它不会这么干,于是,此例中函数 fo 的作用域,也即 f 所代表的函数体(作用域)被留存了下来。
 
   再引申开来,如果 f 这个函数体再执行一次会怎样呢?这时候一个新的函数体又被执行了,一个新的作用域产生又汇入了父级作用域,如果你想销毁这个作用域,又是不可能的。以上面这个例子来说,就有两个值为 1 的变量 x 进入了全局作用域,全局作用域不得不分配两个不同的隐式的变量指向这两个 x ,用行话来说,就是产生了全局污染。 
 
  var f = function( ) {
    var x = 1
    function fo() {
      console.log( x++ )
    }
    fo.alter=function ( n ) {
    x = n
    }
      return fo
  }
  var fn = f()
  fn()              //  1
  fn()              //  2
  fn.alter( 10 ) 
  fn()      //   10
 
  为了给这个函数开一个后门,使得变量 x 可以更改,给函数对象 f 增加一个 alter 的方法。
  关键点在于,此方法也是在 f 的函数体内部定义的,意味着调用也会在此作用域执行,因此更改变量 x 的值也就顺利成章了。
 

JavaScript之更改闭包内的变量值的更多相关文章

  1. SSIS - 4.使用表达式任务和脚本任务实现更改变量和输出变量值

    一.脚本任务 脚本任务是SSIS包中功能很强大的组件,尤其当内置的任务无法实现我们需要的功能的时候,我们都可以使用脚本任务来实现.脚本任务使用VSTA(Microsoft Visual Studio ...

  2. JavaScript交换两个变量值的七种解决方案

    前言 这篇文章总结了七种办法来交换a和b的变量值 1 2 var a = 123; var b = 456; 交换变量值方案一 最最最简单的办法就是使用一个临时变量了,不过使用临时变量的方法实在是太l ...

  3. C#webbrowser控件技巧(取得javascript变量值,禁止显示脚本错误)

    C#中的webbrowser控件比较好用. 下面本人搜索整理的几个小技巧. 1. 从C#中取得javascript的变量值. using mshtml;using System.Reflection; ...

  4. 理解JavaScript变量值

    JavaScript变量可能包含两种不同数据类型的值:基本类型值和引用类型值.基本类型值指的是简单的数据段,而引用类型值是指那些可能由多个值构成的对象. 在将一个值赋给变量时,解析器必须确定这个值是基 ...

  5. JavaScript高级程序设计(复制变量值、传递参数)

    复制变量值 一个变量向另一个变量复制基本类型值和引用类型值时,是存在不同的. 一个变量向另一个变量复制基本类型的值,会在变量的对象上创建一个新值,然后把该值复制到为新变量分配的位置上. var num ...

  6. JavaScript判断变量值简单的方法

    今天在看一个动态web表单设计器的时候发现项目中的 一个写法 function sum_total(v){ if (!v) { v= 0; } } !v  这是什么写法?不过可以肯定的是,这是一种判断 ...

  7. 闭包内的微观世界和js垃圾回收机制

    一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话 ...

  8. 全面理解JavaScript中的闭包的含义及用法

    1.什么是闭包 闭包:闭包就是能够读取其他函数内部变量的函数;闭包简单理解成“定义在一个函数内部的函数”. 闭包的形式:即内部函数能够使用它所在级别的外部函数的参数,属性或者内部函数等,并且能在包含它 ...

  9. Javascript 中的闭包和引用

    Javascript 中一个最重要的特性就是闭包的使用.因为闭包的使用,当前作用域总可以访问外部的作用域.因为Javascript 没有块级作用域,只有函数作用域,所以闭包的使用与函数是紧密相关的. ...

随机推荐

  1. github同一账户+多个库

    目标 我的情况是,既要向自己的public库提交代码,又要向别人的private库提交代码 网上搜到的情况一:github上有多个账号,都要向自己的库提交代码 网上搜到的情况二:多个git托管源(比如 ...

  2. Python的进程与线程--思维导图

    Python的进程与线程--思维导图

  3. sql 约束Check中使用Case函数

    CHECK 约束用于限制列中的值的范围 在Check中使用Case函数在很多情况下都是非常不错的解决方法.可能有很多人根本就不用Check,那么我建议你在看过下面的例子之后也尝试一下在SQL中使用Ch ...

  4. 记录linux配置

    只写成功过程:1.配置sshd: 首先开启安全组端口,选择合适端口(tcp),shell输入vi /etc/services ->ssh修改(21变更为合适端口) 接着shell输入vi /et ...

  5. python-之-深浅拷贝二(元组)

    元组比较特殊 1.----元组本身为不可变类型 import copy v1 = (1, 2, 3, 4) v2 = copy.copy(v1) print(id(v1), id(v2)) v3 = ...

  6. Tensorflow实战系列之二:

    还没想好,可能是人脸检测或者物体检测,或者加上动态检测~~

  7. CentOS6.5 - yum对Mysql的安装与配置

    一.mysql的安装 1.查看是否安装mysql [root@localhost ~]# rpm -qa | grep mysql 如果有进行卸载(以下三种方式选一种即可): -.el6.x86_64 ...

  8. Java泛型之自限定类型

    在<Java编程思想>中关于泛型的讲解中,提到了自限定类型: class SelfBounded<T extends SelfBounded<T>> 作者说道: 这 ...

  9. JVM概念以及常用设置

    DAY 1 Jvm- java虚拟机 类加载子系统 加载class文件到方法区 方法区 存放类信息 常量信息 常量池信息 辅助堆栈的永久区,解决堆栈信息的产生,是先决条件 3.  Java堆(重要) ...

  10. php优秀框架codeigniter学习系列——CI_Input类学习

    这篇文章主要介绍CI核心框架工具类CI_Input. 根据CI文档自己的定义,该类用来: 提前处理全局变量,以保证安全; 提供一些帮助函数用来处理输入数据. 以下选取类中的重点方法进行说明. __co ...