js中的作用域与作用域链

作用域与作用域链

首先先看一个例子:

			let x = 1;
			function A(y){
				let x = 2;
				function B(z){
					console.log(x+y+z)
				}
				return B
			}
			let C = A(2);
			C(3);

先来看以下,js底层代码执行的一个顺序:

ECstack = [		//执行栈

	EC(G)={	//创建全局执行上下文
		VO(G):{	//全局变量对象
		...			//包含全局对象原有的属性
		x=1;
		A=function(y){...}		//创建函数的时候就确定了其作用域  (重点)
		A[[scope]] = VO(G);
}
}
]

注:我们不管在哪一个执行上下文当中,除了创建变量或者堆以外,同时给当前的函数,声明了它所在的作用域是谁。
看上方例子,函数A在全局创建的,那么A的作用域就是全局的执行上下文。当A执行的时候,就会生成一个新的执行上下文(每个函数执行都会生成一个私有的执行上下文)。
此时,在A的执行上下文,我又创建了一个B函数。那么B也会生成一个私有的执行上下文,同时B的作用域也会被创建,那么B是在A的执行上下文创建的,那么B的函数作用域就是,当前这个A的执行上下文。

函数在执行上下文,除了获取arguments(实参对象),生成作用域外,还做了一件事,生成this指向
函数执行,有个执行主体,进来的第一件事情就是声明this指向,this指向后面说。

除此之外,它还初始化了它的链表,也就是我们常说的作用域链。作用域链的查找规则,就是上面加粗的文字。

下面总结一下:
函数的执行机制:
创建函数的时候:
(1)创建一个堆(存储代码字符串和对应的键值对)
(2)初始化了当前函数的作用域[[scope]]
作用域[[scope]]指的是所在上下文EC中的变量对象VO(变量对象)/AO(函数内的变量对象)
严格来说的话。作用域[[scope]] 与执行上下文是有区别的,作用域指的是当前上下文具体的存放变量的地方,上下文是既可以存变量,又能压缩代码放到执行栈执行的。但是,编程中,我们认为他们俩没啥区别,其实也是不会出错的。
函数执行的时候
创建一个新的执行上下文EC,并且压缩至栈(EC stack)里执行。
初始化this指向
初始化作用域链
创建AO变量对象存储变量
变量又会进行 arguments(它是函数运行时的实参对象) =》 形参 --》如果有变量提升,将变量提升,如果没有变量提升,会将代码执行。

下面看一下,上面题闭包的形成,以及作用域链的查找方式
在这里插入图片描述
重:
创建函数的时候,形成的是作用域,以及作用域是谁,函数执行的时候,一定会先初始化好它的作用域链,代码执行当中,遇到一个变量,首先看看它是不是私有变量,如果是,用自己的,如果不是,就会沿着作用域链,一级一级往上查找,一直查找到全局位置,找不到就会报错。这就是闭包,作用域链的一个查找过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

画不完的饼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值