渐进式理解闭包

一、变量作用域

变量的作用域有两种:全局变量和局部变量,而js有特殊的作用域,即:函数内部可直接访问全局变量,而函数外面没法访问函数内的局部变量.

JS代码

  var n = 99;
  function f1(){
    console.log(n);
  }
  f1();//99 
  function f2(){
    var m = 999;//注意点:当在函数内部声明变量时,必须用var命令,否则就会被浏览器认为是全局变量
  }
  console.log(m);//thorw error

二、如何从外部获取局部变量

正常情况下是访问不到的,但是我们解决方法,就是在函数的内部再定义一个函数,把内部函数的作为返回值,就可以解决了。如下:

  function f1(){
    var n = 88;
    function f2(){
      return n;
    }
    return f2;  
  }
  var result = f1();
  result();//88
  //此时,result就是f2这个函数,故需要加()
  result;// function f2(){return n;}

在上面代码中,f2包含在f1内,则f2可访问f1内部的所有变量,反之,不行!即父对象的所有变量对子对象都是可见的.这就是javascript的“链式作用域”

三、闭包的概念

简单来说,上面f2就是闭包函数了,就是能够读取其他函数内部变量的函数。可定义为,在一个函数内部定义的函数,或者说当函数a的内部函数b被a外的一个变量引用时,就创建了闭包。本质上来说,闭包就是将函数内部和外部连接起来的一座桥梁。

四、闭包的用途

有人说,javascript闭包是走向js高级程序员的必经之路,我觉得是很合理的。首先它有两大用途:一方面,可以获取函数内部的变量;另一方面,让这些函数内部变量始终保存在内存中,可随时调用。下面上栗子

  function f1(){
    var n = 77;
    add = function(){//add为全局的匿名函数
      n++;
    }
    function f2(){
      return n;
    }
    return f2;  
  }
  var result = f1();
  result();//77
  add();
  result();//78
  //说明f1的内部变量一直保存着,而没有被清除

五、使用闭包的注意点

  1. 闭包函数中变量都被保存,内存消耗较大,不能滥用,在IE中会导致内存泄漏,解决方法是在函数退出之前,把不适用的内部变量全部清除;
  2. 闭包会在函数外部改变函数内部边变量的值,此时父函数当作对象,闭包为公用方法,内部变量为私有属性,则不可随便修改父函数内部变量的值;

六、闭包的应用场景

  1. 由于函数内部变量不能被外部访问,敢保证了变量的安全性;
  2. 在内存中维持一个变量,由于闭包作用,一直存在于内存中,每次回调执行都会获取到上一步的值;
  3. 通过保护内部变量,实现了js的私有属性和私有方法;

七、Javascript的垃圾回收机制

额外增加的一点,就是垃圾回收机制,在Javascropt中,如果一个对象不再被引用,则这个对象就会被回收;如果两个对象互相引用,而不被第三个对象引用,也会被回收。js有两种垃圾回收机制,一种是标记清除,一种是引用计数

  1. 标记清除:变量进入某个环境时会被标记,离开时标记离开,这种常用
  2. 引用计数:跟踪每个值被引用的次数,当声明一个变量并将一个引用类型的值赋给该变量时,这时该变量的引用计数值+1;相反,如果包含这个值得引用的变量又取得另外一个值,即被重新赋值,那么就-1;当这个值为0时,就回收该变量占用的内存空间

就说这么多,以后会专门写一篇内存回收的,这里只是提及一下。

赏

谢谢你支持我买服务器!

支付宝
微信
  • 闭包
  • javascript

扫一扫,分享到微信

JSONP-跨域获取数据
搜素自动补全下拉列表