什么是闭包

一、闭包的概念

简单来说
闭包就是一个函数+它的词法作用域上要找的变量。

词法作用域

  • 函数在执行的过程中,先从自己的内部作用域找变量;
  • 在自己的内部没有找到的话,就到这个函数声明所在的作用域(即词法作用域)里面去找,依次向上。(最后也没有找到的话就是undefined或报错)
  • 找到的变量是变量当前的状态,而不一定是声明时的状态。

作用域链:作用域链,是由当前环境与上层环境的一系列变量对象组成,它保证了当前执行环境对符合访问权限的变量和函数的有序访问。

闭包使用的意义
 1.封装数据
 2.暂存数据

二、闭包的案例

经典案例:

function car(){
  var speed = 0
  function fn(){
    speed++
    console.log(speed)
  }
  return fn
}

var speedUp = car()
speedUp()   //1
speedUp()   //2

案例一:

var fnArr = [];
for (var i = 0; i < 10; i++){
  fnArr[i] = function(){
    return i
  };
}
console.log(fnArr[3]())  //10

理解:fnArr是一个空数组,然后去遍历这个数组,遍历的时候给数组赋值,这个数组的值为一个匿名函数,fnArr[3]指向的是一个函数,在for循环中遍历的时候,将i已经赋值了,但是在function()中并没有赋值变量i,所以在function中找不到的时候就去它的词法作用域(for循环没有作用域,所以即是全局作用域)里面去找,因为for循环执行完后i的值为10,所以最终输出结果就为10。

改造:

case 1 :
var fnArr = []
for(var i = 0; i < 10; i++){
  fnArr[i] = (function(j){
    return function(){
      return j
    }
  })(i)
}
console.log(fnArr[3]())  //3

case 2:
var fnArr = []
for(var i = 0; i < 10; i++){
  (function(i){
    fnArr[i] = function(){
      return i
    }
  })(i)
}
console.log(fnArr[3]())  //3

case 3:
var fnArr = []
for(let i = 0; i < 10; i++){
   fnArr[i] = function(){
      return i
    }
}
console.log(fnArr[3]())  //3

案例二:封装一个car

var Car = (function(){
   var speed = 0;
   function set(s){
       speed = s
   }
   function get(){
      return speed
   }
   function speedUp(){
      speed++
   }
   function speedDown(){
      speed--
   }
   return {
      setSpeed: setSpeed,
      get: get,
      speedUp: speedUp,
      speedDown: speedDown
   }
})()
Car.set(30)
Car.get() //30
Car.speedUp()
Car.get() //31
Car.speedDown()
Car.get()  //30

你可能感兴趣的:(什么是闭包)