一、闭包的概念
简单来说:
闭包就是一个函数 + 它的词法作用域上要找的变量。
词法作用域:
- 函数在执行的过程中,先从自己的内部作用域找变量;
- 在自己的内部没有找到的话,就到这个函数声明所在的作用域(即词法作用域)里面去找,依次向上;(最后也没有找到的话就是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
case2:
var fnArr = []
for(var i = 0;i < 10; i++){
(function(i){
fnArr[i] = function(){
return i
}
})(i)
}
console.log(fnArr[3]()) //3
case3:
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