这可能是所有问题中最难的一个问题,因为闭包是一个有争议的话题,这里从个人角度来谈谈, 如果不妥,多多海涵。
闭包就是一个函数在声明时能够记住当前作用域、父函数作用域、及父函数作用域上的变量和 参数的引用,直至通过作用域链上全局作用域,基本上闭包是在声明函数时创建的作用域。
看看小例子:
//全局作用域
var globalVar = "abc";
function a() {
console.log(globalVar);
}
a(); // "abc"
在此示例中,当我们声明a函数时,全局作用域是a闭包的一部分。
变量globalVar在图中没有值的原因是该变量的值可以根据调用函数a的位置和时间而改变。 但是在上面的示例中,globalVar变量的值为abc。
来看一个更复杂的例子:
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。
当我们调用outerFunc函数并将返回值innerFunc函数分配给变量x时,即使我们为outerVar 变量分配了新值outer-2,outerParam也继续保留outer值,因为重新分配是在调用outerFunc 之后发生的,并且当我们调用outerFunc函数时,它会在作用域链中查找outerVar的值,此 时的outerVar的值将为"outer"。
现在,当我们调用引用了 innerFunc的x变量时,innerParam将具有一个inner值,因为这 是我们在调用中传递的值,而globalVar变量值为guess,因为在调用x变量之前,我们将一 个新值分配给globalVar。
下面这个示例演示没有理解好闭包所犯的错误:
const arrFuncs =[];
for (var i = 0; i < 5; i++) {
arrFuncs. push(function (){
return i;
});
}
console. log(i) ; // i is 5
for (let i = 0; i < arrFuncs. length; i++) {
console. log(arrFuncs[i] ()) ; // 都打印 5
}
由于闭包,此代码无法正常运行。var关键字创建一个全局变量,当我们push 一个函数时, 这里返回的全局变量i。因此,当我们在循环后在该数组中调用其中一个函数时,它会打印5, 因为我们得到i的当前值为5,我们可以访问它,因为它是全局变量。
因为闭包在创建变量时会保留该变量的引用而不是其值。我们可以使用IIFES或使用let来 代替var的声明。

Was this helpful?

0 / 0

发表回复 0

Your email address will not be published.