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. C#中自定义高精度Timer定时器的实例教程

    Timer 用于以用户定义的事件间隔触发事件.Windows 计时器是为单线程环境设计的,其中,UI 线程用于执行处理.它要求用户代码有一个可用的 UI 消息泵,而且总是在同一个线程中操作,或者将调用 ...

  2. PHP 2个比较经典的加密解密函数

    这篇文章主要介绍了2个比较经典的PHP加密解密函数分享,一个是Discuz!的authcode加密函数(带详细分解),一个是encrypt()函数,都比较经典,需要的朋友可以参考下 项目中有时我们需要 ...

  3. qr-mili Tekniskt stöd

    qr-mili Är ett QR-kodverktyg Identifiera enkelt QR-koder Generera QR-kod Skapa en QR-kod med logotyp ...

  4. Django知识总结(三)

    拾伍 ● Ajax技术 一 ● Ajax定义 Ajax: 异步的 JavaScript 和 XML (Asynchronous+Javascript+XML) 通过Ajax, 我们可以在不重新加载整个 ...

  5. 201671010142 2017-2 《java第十二十三章学习感悟》

    Swing编程第一步,需要导入Swing相关包,即javax.swing.*. 接下里需要设置界面外观风格,使用到UIManager类. 设置完外观之后一定要调用 SwingUtilities.upd ...

  6. ubuntu 16.04 安装 opencv +contrib (3.2.0) + python 3.5

    环境: - ubuntu 16.04 - OpenCV + contrib 3.2.0 (文中附下载链接) - Python 3.5 基于其他环境的配置应该大同小异. 没时间解释了,直接上车. 更新下 ...

  7. javascript--返回顶部效果

    window.onload = function(){ var obtn = document.getElementById('btn'); //客户端页面可视区高度 var clientHeight ...

  8. (一)java异常处理的几个问题

    1.java中两种异常? 答:java中存在两种异常:受检查(checked)异常和不受检查(unchecked)异常.不受检查的异常不需要在方法或者构造函数上声明,就算是方法或是构造函数会发生这样的 ...

  9. linux 查看并对外开放端口(防火墙拦截处理)

    [转]https://blog.csdn.net/qq564425/article/details/80760528 Web应用在Tomcat部署后无法访问,可能是防火墙端口限制导致 查看端口是否可访 ...

  10. numpy 库使用

    numpy 库简单使用 一.numpy库简介 Python标准库中提供了一个array类型,用于保存数组类型的数据,然而这个类型不支持多维数据,不适合数值运算.作为Python的第三方库numpy便有 ...