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. stackExchange.redis 实现模糊匹配批量查询

    如果使用redis的频次较高,那么业务中经常会出现需要根据关键字进行批量查询,所以总结一下StackExchange中使用批量查询的方法(如果数据量很大,那么在redis中模糊查询很耗时,请慎用!) ...

  2. 一面(3) react方面

    1.react的声明周期 getDefaultProps() getInitialState() componentWillMount()       以后组件更新不调用, 只调用一次        ...

  3. R语言RODBC数据库操作

    最近准备做一个股票的数据库,用R语言来获取数据,然后存在SQL Sever 2016 express 里面,虽然前面接触过一些操作,但是还是很不熟悉,现在数据已经能获取到了,是时候好好学习一下怎么用R ...

  4. runtime统计页面数据或者统计按钮的点击次数

    一.按钮的点击统计 有的时候我们遇见这样的需求,让我们统计用户点击我们页面的动作的次数给与用户以统计,供以后给客户端推送不同的页面数据,这时候我们就会用到iOS的黑魔法(runtime). 首先我们不 ...

  5. Docker run 命令

    docker run -d -p 8084:80 --name weather --restart always --link fme-postgis 192.168.1.220:5000/weath ...

  6. 第一次作业_ChenHong1998

    我的目标 学习到软件工程的实践过程 回想一下你初入大学时对软件工程专业的畅想 当初你是如何做出选择软件工程专业的决定的? 计算机是热门专业,软件工程专业好找工作 你认为过去两年中接触到的课程是否符合你 ...

  7. js事件、事件流以及target、currentTarget、this那些事

    你是如此简单我却将你给遗忘   前面面试被问到js的事件机制  target.currentTarget.碰巧今天有时间来拔一拔,顺便记下.

  8. java集合(二)

  9. myeclipse 修改用户名密码

    当在一台公共的电脑上开发程序时,就需要涉及到更改svn用户名和密码,不然直接用本机用户密码提交,有点不妥. win7系统解决方案: C:\Documents and Settings\Administ ...

  10. css 清楚浮动的几种方式

    方法一: 使用clear属性的空元素 <div style="clear:both;"></div> 方法二:使用overflow属性 给浮动的元素容器添加 ...