JS函数闭包closure

什么是闭包

闭包是指:有权访问另一个函数作用域中变量的函数。

  • 创建方式:在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域。
  • 目的:将函数内部的变量和方法传递到外部。

闭包的原理

借助函数的立即执行、参数以及函数的return返回值,多创建了一层作用域。从而实现外部函数持续性被引用而不能释放内存空间,将值存储下来。


闭包的作用

闭包就是将函数内部和函数外部连接起来的一座桥梁。使得外部函数可以读取内部函数的变量,这些变量的值始终保持在内存中,不会被垃圾回收器回收。


闭包的优点

  1. 避免全局变量被污染
  2. 方便调用上下文的局部变量
  3. 加强封装性

闭包的缺点

  1. 闭包常驻内存,内存消耗很大。
  2. 如果内存回收机制有缺陷,可能引起内存泄漏。由于闭包创建了循环引用,就是说A对象包含一个指向B的指针,对象B也包含一个指向A的引用。 这就可能造成大量内存得不到回收(内存泄露),因为它们的引用次数永远不可能是 0 。
  3. 因此在退出函数之前,将不使用的局部变量全部删除来避免。
// 这段代码会导致内存泄露
window.onload = function(){
    var el = document.getElementById("id");
    el.onclick = function(){
        alert(el.id);
    }
}

// 解决方法为
window.onload = function(){
    var el = document.getElementById("id");
    var id = el.id; //解除循环引用
    el.onclick = function(){
        alert(id); 
    }
    el = null; // 将闭包引用的外部函数中活动对象清除
}

闭包的实际应用

var oli = document.getElementsByTagName('li');
var i;
for(i = 0;i < 5;i++){
    oli[i].onclick = function(){
        alert(i);
    }
}

执行结果是都弹出5。

解释:for循环中,给每个li点击事件绑定了一个匿名函数,匿名函数中返回了变量i的值,当循环结束后,变量i的值变为5,此时我们再去点击每个li,也就是执行相应的匿名函数(看上面的代码),这是变量i已经是5了,所以每个点击弹出5.

因为这里返回的每个匿名函数都是引用了同一个变量i,如果我们新建一个变量保存循环执行时当前的i的值,然后再让匿名函数应用这个变量,最后再返回这个匿名函数,这样就可以达到我们的目的了,这就是运用闭包来实现的!