当面试官让你说说闭包时

61 阅读2分钟

闭包

回答要素:

  1. 作用域链
  2. 执行上下文
  3. 函数的活动对象(即参数)
    1. 函数局部上下文中的叫活动对象,只在函数执行期间存在
    2. 全局上下文中的叫变量对象,它会在代码执行期间始终存在
  1. 垃圾回收

定义

闭包的本质其实是一个函数,但是特殊在于这个函数会引用另一个函数作用域中的变量

作用域链

定义

作用域链的本质是什么?是一个包含指针的列表,每个指针分别指向一个变量对象

先来看一个普通函数的作用域链

function compare(value1, value2) {
	if (value1 < value2) {
		return -1;
	} else if (value1 > value2) {
		return 1;
	} else {
		return 0;
	}
}
let result = compare(5, 10);
  1. 定义compare函数
    1. 创建作用域链,预装载全局变量对象
  1. 调用compare函数
    1. 装载活动对象,value1和value2
  1. 定义result变量
  2. 调用结果复制给result

重点

作用域链决定了各级上下文中的代码在访问变量和函数时的顺序

执行上下文

定义

变量或函数的上下文决定了它们可以访问哪些数据,以及它们的行为

所以说

决定变量或函数可以访问哪些数据,以及他们行为的域就叫做执行上下文

重点
  1. 上下文在其所有代码都执行完毕后会被销毁,包括定义在它上面的所有变量和函数(全局上下文在应用程序退出前才会被销毁,比如关闭网页或退出浏览器)
  2. 全局上下文是最外层的上下文
  3. 每个函数调用都有自己的上下文

垃圾回收

闭包中的变量不会被自动垃圾回收,需要手动清除

正常来说,一个函数执行完之后,会自动回收里面的变量,外部的函数或对象访问不到里面的变量了

var color = "blue";
function changeColor() {
	let anotherColor = "red";
	function swapColors() {
		let tempColor = anotherColor;
		anotherColor = color;
		color = tempColor;
		// 这里可以访问 color、anotherColor 和 tempColor
	}
	// 这里可以访问 color 和 anotherColor,但访问不到 tempColor
	swapColors();
}
// 这里只能访问 color
changeColor();

就比如changeColor访问不到tempColor

闭包的话,比如下面这个例子

const _count = function(){
	var num = 1;
	return function(){
		return num++;
	}
}

内部的匿名函数保持着对num的引用,所以num不会被自动回收