JS闭包

闭包的概念

在高程三中对闭包的定义是这样的:闭包是指有权访问另一个函数作用域中变量的函数。其实就是函数A返回了一个函数B,并且函数B使用了函数A的变量,函数B就被称为闭包。

function A(){
  var a = 'a';
  function B(){
    alert(a)
  }
  return B
}

在js中变量的作用域分为两种:全局变量和局部变量

var n = 123;
function fn(){
  alert(n)
}
fn();  //123

在函数内部可以直接访问全局变量,但要在外部访问函数内部的变量呢?

function fn(){
  var n = 123;
}
alert(n);  //n is not defined   

可以看到直接报错了,显示n没有被定义,由于种种原因我们需要得到内部变量,我们可以在函数内部再定义一个函数,然后把这个函数返回出来,这样我们能就可以取到函数内部变量

function fn(){
  var n = 123;
  function fn2(){
    console.log(n)
  }
return fn2
}
var result = fn();
result();  //123

在上面代码中fn()的所有局部变量相对于fn2()是可见的,但反过来就不行,fn2()的局部变量对于fn()就是不可见的,如此我们就可以把fn2作为返回值,在fn外部就可以访问fn内部的变量了。
这就是“链式作用域”:子对象可以一级一级的向上寻找所有父对象的变量,所以所有父对象的变量对子对象都是可见的,反之则不行。

闭包的用途

闭包可以被用在很多地方,它最大的用处有两个:一个是上文提到的在函数外部获取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。我们会经常遇到这种情况:

for(var i=0; i <= 5; i++){
  setTimeout(function (){
      console.log(i)
   },1000)
}

首先因为setTimeout()是个异步函数,所以会先把循环全部执行完毕,这时候i就等于6了,所以会输出一堆的6.要解决这个问题就要用到闭包:

for (var i=0; i <= 5; i++){
  (function (n){
    setTimeout(function (){
      console.log(n)
    },1000)
  })(i)
 
}

其实要解决这个问题还有两种方法,第一种就是使用setTimeout()的第三个参数

for (var i=0; i <= 5; i++){
  setTimeout(function (n){
      console.log(n)
  },1000,i)
}

还有一种就是使用let声明变量,let会创建一个块级作用域

for (let i=0; i <= 5; i++){
  setTimeout(function (){
      console.log(i)
  },1000)
}

使用闭包的注意点

闭包会使函数的变量都保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE浏览器会造成内存泄漏。所以在退出函数之前应把不使用的局部变量清空。

    原文作者:哎呦_連啓
    原文地址: https://www.jianshu.com/p/c8aac49bf748
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞