0
点赞
收藏
分享

微信扫一扫

明白闭包,你还差两张图

未定义变量 2022-03-31 阅读 95

机缘

今儿又有人问我闭包的原理,我是连写代码带比划的和他说了半天,
可看他依然似懂非懂的表情,我也是慢慢的挫败感.
在这里插入图片描述

解释几个概念

  1. 函数执行是,每个执行上下文都会一个包含其中变量的对象.
  2. 全局上下文中叫做变量对象,代码执行期间始终存在.
  3. 函数局部上下文叫活动对象,只在函数执行期间存在.
  4. 上下文之的就是某段代码的运行环境,在执行前的几毫秒生成,可参考另一篇文章上下文就是煮一碗泡面
  5. 作用域链:上下文代码执行时,利用变量对象创建的,决定了各级上下文中代码访问变量和函数的顺序.

普通函数

        function compare(value1,value2){
				if(value1<value2){
					return -1;
				}else if(value1>value2){
					return 1;
				}else{
					return 0;
				}
			}
			
			let result = compare(5,10);
			console.log(result);

分析一波

  • compare() 函数在全局上下中调用,第一次调用compare时,会为它创建一个活动对象.
  • 活动对象中包括,value1,value2和arguments等值.
  • 该活动对象是compare()作用域链中的第一个对象.
  • 而全局上下文的变量对象是compare作用域链上的第二个对象.其中包含this,result和compare()
    图示如下
    在这里插入图片描述
  • 函数内部代码在访问变量时,就会从给定作用域链中查找.
  • 函数执行完毕局部活动对象被销毁内存只剩下全局变量对象,不过闭包就不一样.

闭包函数

	function createComparisonFunction(){
		return function (value1,value2){
				if(value1<value2){
					return -1;
				}else if(value1>value2){
					return 1;
				}else{
					return 0;
				}
			}
	}
	let compare = createComparisonFunction('name');
	let result = compare({name:'Nichoias'},{name:'Matt'})

分析一波:

在这里插入图片描述

  1. createComparisonFunction返回闭包后,它的作用域链被初始还为包含createComparisonFunction的活动多对象和全局变量对象.
  2. 如此,匿名函数就可以访问createComparisonFunction可以访问的所有变量.
  3. 不好的地方就是它的活动对象不能在它执行完毕时销毁,因为匿名函数的作用域链仍然对它有引用.
  4. 一直到匿名函数被销毁,其活动对象才会被销毁.

优化

// 解除对函数的引用,这样就可以释放内存了
let compare = createComparisonFunction('name');
compare = null;
  • 设置为null,解除对函数的引用,从而让垃圾回收程序可以将内存释放出来.
  • 作用域链也会被销毁.

注意

  • 闭包会保留相关(自己,及父级)函数的作用域,所以比其他函数更占用内存.
  • 所以必须在十分必要的时候采去使用.
举报

相关推荐

0 条评论