理解闭包

2020-04-22  本文已影响0人  KATENGC

一、闭包的概念

我们先来看一个简单的函数

function foo(){
  var a=10;
  return a;
}

foo();// 2

这里我声明了一个foo的函数,在该函数中有一个变量a,这个a属于局部变量,其作用域仅在函数中有效。
这里调用结束后,这里的局部变量是可以被释放(与js的垃圾回收机制相关)了,正常来说foo函数调用完毕,为局部变量a分配的空间就会被回收了。

我们稍微改动下上面的函数

function foo(){
  var a=20;
  return function(){
    return a;
  }
}

var func=foo();
func();// 20

这里我们可以看到foo函数的返回是一个匿名函数,而这个匿名函数返回的是局部变量a。当执行foo()后,这个局部变量是不会被回收的,这就形成了一个闭包,我们在外部仍然可以调用变量a。

我们来总结下。正常来说,函数内部的变量只能在该函数内使用,在函数外部是不能调用的,而闭包就是定义在函数内部的子函数,子函数中用到了父函数的参数或局部变量,局部在函数调用之后参数或者局部变量不会被回收,同时这个局部变量能在函数外部被调用到。(个人理解)

二、闭包的作用

那闭包的作用是什么呢?

1.具有封闭性,可以保护变量不被回收

function foo(){
  var num=1;
  function b(){
    num++;
    return num;
  }
  return b
}

var func=foo();
func();// 2
func();// 3

上面我们可以看到,在foo函数中有定义了一个子函数b,而这个子函数中使用了上一级(父函数)中的局部变量num,所以就导致foo()调用后,这个局部变量num不会被回收。foo()返回一个函数,赋值给了func,第一次调用func()返回num++后的值(num=2)这个时候num就会保存起来了,不会被回收,第二次调用func()返回num++值(在num=2的基础上,在加1,num=3)

2.避免全局变量污染

var a=1;
function foo(){
  a++;
  return a;
}

foo();// 2
foo();// 3

此时的a是全局变量,在程序中尽可能避免全局变量。那我们将变量a放到函数内试试

function foo(){
 var a=1;
 a++;
 return a;
}

foo();// 2
foo();// 2

可以看到每一次foo()的执行结果都是2。这是因为变量a为foo函数的局部变量,每一次调用foo()完毕后,变量a都会被GC回收,下一次执行的时候,a又初始化为1,累加后输出2,所以永远输出的都是2

那有没有办法能使局部变量a既避免被全局污染又能做到不会GC回收呢?
答案是有的,我们可以利用闭包实现

function foo(){
  var a=1;
  function b(){
    a++;
    return a;
  }
  return b;
}

var func=foo();
func();// 2
func();// 3

三、使用闭包需要注意什么

(1)因为闭包会导致局部变量会保存在内存中,这对内存消耗是很大的,所以不能滥用闭包,否则会影响网页的性能,在IE中可能会导致内存泄漏。如何解决?

window.onload = function(){
    var oDiv = document.getElementById('div1');
    oDiv.onclick = function(){
        alert(oDiv.id);
    }
    //当页面跳转的时候把oDiv.onclick引用置为空就好了
    window.onunload = function(){
        oDiv.onclick = null;
    }
}

(2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象使用,把闭包当作它的公用方法,把内部变量当作它的私有属性,这时一定要小心,不要随便改变父函数内部变量的值

上一篇 下一篇

猜你喜欢

热点阅读