什么是闭包?

发布于:2024-06-12 ⋅ 阅读:(153) ⋅ 点赞:(0)

一个函数在声明时能够记住当前作用域、父函数作用域及父函数作用域上的变量和参数的引用,直至通过作用域链上全局作用域,基本上闭包是在声明函数时创建的作用域

1、简单例子

// 全局作用域
var globalVar = "abc";
function a(){
  console.log(globalVar);
}
a(); // abc

在此示例中,当声明 a 函数时,全局作用域是 a 闭包的一部分

变量 globalVar 在图中没有值的原因是该变量的值可以根据调用函数a的位置和时间而改变。但是在上面的示例中,globalVar 变量的值为 abc

2、复杂例子

var globalVar = "global";
var outerVar = "outer"

function outerFunc(outerParam) {
  function innerFunc(innerParam) {
    console.log(globalVar, outerParam, innerParam);
  }
  return innerFunc;
}

const x = outerFunc(outerVar);
outerVar = "outer-2";
globalVar = "guess"
x("inner");//guess outer inner

(1)当调用 outerFunc 函数并将返回值 innerFunc 函数分配给变量 x 时,即使为 outerVar 变量分配了新值 outer-2,outerParam 也继续保留 outer 值,因为重新分配是在调用 outerFunc 之后发生的

(2)当调用 outerFunc 函数时,它会在作用域链中查找 outerVar 的值,此时的 outerVar 的值将为 "outer"

(3)当调用了 innerFunc 的 x 变量时,innerParam 将具有一个 inner 值,因为这是在调用中传递的值,而 globalVar 变量值为 guess,因为在调用 x 变量之前,我们将一个新值分配给 globalVar

3、错误例子

const arrFuncs = [];
for(var i = 0; i < 5; i++){
  arrFuncs.push(function (){
    return i;
  });
}
console.log(i); // 5

for (let i = 0; i < arrFuncs.length; i++) {
  console.log(arrFuncs[i]()); // 5个5
}

(1)var 关键字创建一个全局变量,当 push 一个函数时,这里返回的全局变量 i,在循环后,在该数组中调用其中一个函数时,它会打印5

(2)闭包在创建变量时,会保留该变量的引用而不是其值。可以使用 IIFES 或使用 let 来代替 var 的声明


网站公告

今日签到

点亮在社区的每一天
去签到