【JS基础】预编译、作用域&作用域链、闭包

预编译

js的执行顺序

  • 语法分析
  • 解释执行

预编译什么时候发生

  • 预编译分为全局预编译和局部预编译
  • 全局预编译发生在页面加载完成时执行
  • 局部预编译发生在函数执行的前一刻

预编译步骤

  • AO(Activation Object) 活动对象,也叫执行期上下文,作用域。这里指的时函数的局部作用域
  • GO(Global Object) 全局对象,与window对象相同
  • GO时全局预编译,会优先于AO创建执行

局部预编译步骤

  • 创建AO(Activation Object)对象
  • 寻找形参和变量声明,变量和形参作为AO对象的属性名,赋值为undefined
  • 实参赋值给形参
  • 找函数声明、赋值
  • 执行

全局预编译步骤

  • 创建GO对象(Global Object)全局对象。
  • 找变量声明,将变量名作为GO属性名,值为undefined
  • 查找函数声明,作为GO属性,值赋予函数体

例子

例1
function test(a){
	console.log(a);
	var a = 1;
	console.log(a);
	function a(){}
	console.log(a);
	var b =function (){};
	console.log(b);
	function d(){};
}
test(2);

打印结果:
 	ƒ a(){}
 	1
 	1
 	ƒ (){}
创建AO
	AO={}
找变量声明
	AO={
		a:undefined,
		b:undefined,
	}
实参赋值
	AO={
		a:2,
		b:undefined
	}
寻找函数声明
AO={
	a:function a(){},
	b:undefined
	d:function d(){}
}
执行函数
	AO={
		a:function a(){}->1,
		b:undefined->function(){},
		d:function d(){}
	}
例2
function test(a,b){
	console.log(a);
	c=0;
	var c;
	a=5;
	b=6;
	console.log(b)
	function b(){};
	function d(){};
	console.log(b);
}
teset(1)
打印结果:
	1
	6
	6
创建AO
	AO={}
找变量声明
	AO={
		a:undefined,
		b:undefined,
		c:undefined,
	}
实参赋值
AO={
	a:1,
	b:undefined,
	c:undefined,
}
寻找函数声明
	AO={
		a:1,
		b:function b(){},
		d:function d(){},
		c:undefined,
	}
执行函数
	AO={
		a:5,
		b:6,
		d:function d(){},
		c:0,
	}
例3
var a =1;
function a(){
	console.log(2);
}
console.log(a);
创建GO
	GO={}
寻找变量声明
	GO={
		a:undefined
	}
找函数声明
	GO={
		a:undefined
	}
执行
	GO={
		a:1,
	}
例4
console.log(a,b);
function a(){
	console.log(2);
}
var b =function(){};
ƒ a(){
	console.log(2);
} 
undefined
创建GO
	GO={}
寻找变量声明
	GO={
		a:undefined,
		b:undefined
	}

找函数声明
	GO={
		a:function(){},
		b:undefined
	}
执行
	GO={
		a:function(){},
		b:undefined
	}
例5
var b = 3;
console.log(a);
function a(a){
	console.log(a);
	var a =2;
	console.log(a);
	function a(){};
	var b=5;
	console.log(b);
}
a(1);
打印结果:
	ƒ a(){}
 	2
 	5
创建GO
	GO={}
寻找变量声明
	GO={
		a:undefined,
		b:undefined
	}
找函数声明
	GO={
		a:function(){},
		b:undefined
	}
执行
	GO={
		a:function(){},
		b:3
	}
创建AO
	AO={}
找变量声明
	AO={
		a:undefined,
		b:undefined,
	}
实参赋值
	AO={
		a:1,
		b:undefined,
	}
寻找函数声明
	AO={
		a:function a(){},
		b:undefined,
	}
执行函数
	AO={
		a:2,
		b:5,
	}

作用域&作用域链

  • 每个对象都有一个[[scope]]
    • 函数创建时,生成的一个个js内部的隐式属性
  • 函数存储作用域的容器叫做作用域链
    • AO 函数的执行期上下文
    • GO 全局的执行期上下文
  • 函数执行完成后,AO是要销毁的。每次执行都会产生一个新的AO
  • 全局上下文GO在应用程序推出前才会被销毁。(关闭网页,推出浏览器)
  • 当代码执行到函数时,函数的上下文被推到一个上下文栈中。该函数执行完毕,上下文栈会弹出该上下文,将控制权返还给之前的执行上下文
function a(){
	function b(){
		var b = 2;
	}
	var a = 1;
	b();
}
var c = 3;
a();

当a函数定义&执行前

在这里插入图片描述

当b函数定义&执行前

在这里插入图片描述

当a函数&b函数执行结束

在这里插入图片描述

为什么外部访问不到内部的变量?

  • 查找变量的时候,会从作用域链的顶端开始查询
  • 外部执行期上下文不包含内部的执行器上下文

闭包

当内部函数被返回到外部并保存的时候,就一定会产生闭包

  • 闭包会产生原来的作用域链不释放
  • 过度的闭包可能会导致内存泄漏或加载过慢
function test1(){
	function test2(){
		var a = 2;
		console.log(a);
	}
	var a = 1;
	return test2;
}
var c = 3;
var test3 = test1();
test3();

闭包的产生

test1执行完毕时

在这里插入图片描述

test3执行时

在这里插入图片描述

test3执行完毕时

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值