一、变量的作用域

要理解js的闭包,首先要了解js的变量作用域;

(1)js的变量有两种:全局变量,局部变量;

js的局部变量只会在函数内部通过var声明产生,不是通过var声明的变量也会被当成局部变量

    var a = 'a';
    function myFunc() {
      var b = 'b';
      c = 'c';
    }
    myFunc();
    console.log(a); // output: a
    console.log(c); // output: c
    console.log(b); // output: Uncaught ReferenceError: b is not defined

上面结果:a, c都能在全局访问,都是全局变量, b不能再全局访问,所以是局部变量。c虽然定义在内部,但是由于没有通过var时声明,所以是全局变量。

(2)变量的作用域

看下面的例子:

    var a = 'a';
    function myFunc() {
      var b = 'b';
      console.log('inner func:', a); // a
      console.log('inner func:', b); // b
    }
    myFunc();
    console.log(a); // output: a
    console.log(b); // output: Uncaught ReferenceError: b is not defined

从上面的例子可以看出,函数内部可以读取函数外部的变量,而函数外部不可以读取函数内部的变量。

 

二、闭包

某些情况下,需要在函数外部访问函数内部的变量,正常情况是办不到的。但是我们可以想个办法:在函数内部再定义一个函数,然后再把该函数作为返回值返回,我们就可以实现在函数的外部,读取函数内部的变量了。而作为返回值的这个函数就是闭包。

function f1() {

   var n = 999;
    function f2() {
      console.log(++n)
      }
   return f2;
 }
f2就是闭包,可以让外部访问内部函数的变量n。
有些人会有疑问,在f1中直接返回n不也可以让外部访问内部函数的变量了吗?就像下面这样:
    function f1() {
      var n = 999;
      return ++n;
    }
    var result1 = f1(); // 1000
    var result2 = f1(); // 1000
上面虽然能访问变量,但是n在函数执行完之后就被销毁了,没有被保存下来。但是用下面的这个方法,虽然外部函数在执行完之后被销毁了, 但是n就被保存下来了:
function f1() {

  var n = 999;
  function f2() {
    return ++n;
  }
  return f2;
}

var result = f1();
result(); // 1000
result(); // 1001
result(); // 1002

因此闭包有两个用处:(1)可以使函数外部读取函数内部的变量; (2)让函数内部的变量始终保存在内存中。

因为闭包会使函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决放法是:在退出之前, 将不使用的局部变量全部删除;

posted on 2019-05-10 17:20  yyy_鸳鸯  阅读(104)  评论(0编辑  收藏  举报