4.通过示例了解JavaScript闭包

87 阅读4分钟

通过示例了解JavaScript闭包

让我们从理解另一个名为​闭包​的JavaScript基础开始。

闭包简介

闭包​被认为是JavaScript中的一个高级概念。完全理解这个概念可能需要一段时间。但是,不要担心。正如您在本系列的前几篇文章中了解的执行上下文、范围和范围链的基础知识一样,它对您来说会简单得多。

让我们从一个简单的代码示例开始,

function sayHello(msg) { 
  return function(name) { 
	console.log(`${name}! ${msg}`);
  }
}

这里我们有一个函数​sayHello()​,它将消息作为参数。在JavaScript中,函数可以返回另一个函数。​sayHello()​返回一个函数,该函数将​name​作为参数,并在控制台中记录名称和消息。​sayHello()​中的函数称为内部函数,​sayHello()​可以称为外部函数。

很公平。我们如何调用它们?在这里,

var messageFor = sayHello('Hello, there!');
console.log(messageFor('Jack'));

正如​sayHello()​返回一个函数,变量​messageFor​指向一个函数。在下一行中,我们调用​messageFor​传递值“Jack”。它记录以下输出,

Jack! Hello, there!

但是,我们有几个问题知道

  • sayHello()​的内部函数如何获得对​msg​变量的访问权限?这怎么可能?
  • 这里的作用域​呢?msg​变量绝不在内部函数的范围内。那它是怎么工作的?

答案是,它在一个名为​闭包​的JavaScript功能的帮助下工作

有点总结

现在,我们意识到,

  • 有一种称为全局执行上下文​​和函数执行上下文​​的东西。
  • 当JavaScript程序运行时,会创建一个全局执行上下文。
  • 调用函数时,会创建函数执行上下文
  • 所有函数执行上下文都指及其外部环境,即创建当前运行函数的函数的执行上下文。
  • 使用外部引用,JavaScript引擎确定变量的可访问性。这称为​作用域​。
  • 可以通过遍历导致全局执行上下文的作用域链来找到变量的作用域。

我们以前见过这张照片,

闭包分析

在JavaScript中,一个函数可以嵌套在另一个函数中。嵌套的函数称为内部函数​。这个内部函数可以访问外部函数上下文中定义的变量。它是通过闭包​完成的。所以,是内部函数创建了外部函数的闭包。

让我们更详细地了解上面示例的执行步骤。这又是代码

function sayHello(msg) { 
	return function(name) { 
		console.log(`${name}! ${msg}`); 
	}
} 

var messageFor = sayHello('Hello, there!'); 

console.log(messageFor('Jack'));
  • 创建一个全局执行上下文。在其执行阶段​,调用函数​sayHello()
var messageFor = sayHello('Hello, there!');
  • sayHello()​创建了一个函数执行上下文,并将其添加到执行堆栈中。请注意,它有一个名为msg​的参数,它将在其执行上下文中可用。
 function sayHello(msg) { 
 }
  • sayHello()​返回另一个函数并弹出执行堆栈
 function sayHello(msg) { 
 	return function(name) {
 	 console.log(`${name}! ${msg}`);
  }
}

sayHello()​返回一个内部函数。这意味着,内部函数将创建一个对外部函数(sayHello()​)执行上下文的闭包​。这样,它也将拥有对外部函数变量的所有访问权限。在这种情况下,它是msg​。

  • 接下来,全局执行上下文调用​messageFor('Jack')​。这只不过是最后一步中返回的内部函数。
 console.log(messageFor('Jack'));

此调用将创建一个新的函数执行上下文。当我们将Jack​作为参数传递时,它将在其执行上下文中可用。但请记住,它也可以访问上述步骤中解释的msg​。

这就是闭包​如何帮助保留对父级执行上下文的访问,即使它已经被执行并从执行堆栈中删除。

这是一个引人注目的概念。我希望它更容易理解。还没有?好吧,让我们直观地看到所有这些发生,

内部函数在外部函数的执行上下文上创建了一个名为闭包作用域​的特殊范围。这就是​闭包作用域​的样子(红色边框),

试试这个例子

你认为下面会是什么?

function myMultiplier(x) { 
	return function inner(y) { 
		return x * y;
  }
}

然后调用函数,例如,

var multiplyOf5 = myMultiplier(5);
var multiply5x4 = multiplyOf5(4);
console.log(multiply5x4);

我肯定你明白了!是的,内部函数将可以访问父函数(myMultiplier())执行上下文的变量。内部函数现在在范围内有两个变量,i、e、x和y。

在执行阶段,x和y的值分别为5和4。这些乘法的结果是20。现在不是很简单吗?