javascript中的函数作用域链

函数对任何一门语言来说都是核心的概念。通过函数可以封装任意多条语句,而且可以在任何地方、任何时候调用执行。在javascript里,函数即对象,程序可以随意操控它们。函数可以嵌套在其他函数中定义,这样它们就可以访问它们被定义时所处的作用域中的任何变量,函数里边能访问函数外边的变量,但函数外边不能访问函数里边的变量它给javascript带来了非常强劲的编程能力。

关于js中函数的作用域链,要想理解函数的作用域链,首先我们得引出几个重要的概念。
执行期上下文:当函数执行时,会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被 “销毁”。
函数定义的时候会产生一个全局的作用对象我们称之为GO对象
函数调用的前一刻产生的执行期上下文我们称之为AO对象

作用域[[scope]]:每个js函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供js引擎存取,[[scope]]就是其中一个。[[scope]]其中存储了运行期上下文的集合。

作用域链:[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式连接,我们把这种链式连接叫做作用域链。

结合着例子来理解一下:

function a() {
	function b() {
		var b=234;
	}
}
var glob = 100;
a();

a函数被定义时发生如下过程:

在这里插入图片描述

先不要细琢磨上面GO里放置的各个属性。上面a.[[scope]]还没有构成一个链,只有GO对象的存在,下面继续。

a函数被执行时,发生如下过程:
在这里插入图片描述

a函数执行前一刻所产生的AO对象放到了a函数作用域a.[[scope]]的顶端;现在a.[[scope]]上已构成一个链.

  • 查找变量:从作用域链的顶端依次向下查找(再补充:在哪个函数里查找变量,就去哪个函数的作用域顶端去查找),最标准的说法。

    再继续研究刚刚的例子:

    function a() {
    	function b() {
    		var b=234;
    	}
    }
    var glob = 100;
    a();
    

    b函数被创建时,发生如下过程:
    在这里插入图片描述

    也就是说b函数刚刚出生时所在的环境是a执行的结果,直接给b函数的出生创造好了环境。

    b函数被执行时,发生如下过程:

b函数执行前一刻产生的AO对象放置在b.[[scope]]的最顶端。现在透彻地理解一下,在函数b中去访问变量时,是在b函数的作用域[[scope]]最顶端去查找变量。

需要注意的一点 第7行b函数执行完之后,自己的执行期上下文AO被干掉(销毁),即b.[[scope]]回到b被定义的状态。(即此时b函数的作用域链就是a的作用域链

  • 往下进行到第9行,a函数执行完后,b函数作用域b.[[scope]]直接被销毁,因为b函数的作用域链创建于a的执行期上下文AO之上;同时,a函数的执行期上下文AO被干掉(销毁),a.[[scope]]回到被定义的状态,a函数等待下一次被调用执行。

我们在看一下下面函数执行的作用域链:

function a() {
	function b(){
		function c() {
		
		}
		c();
	}
	b();
}
a();

具体过程如下

a 定义:  a.[[scope]]    --> 	0:GO

a 执行:  a.[[scope]]    --> 	0:AO(a)
		      				 1:GO
		      				 
b 定义:  b.[[scope]]    --> 	0:AO(a)
		      				 1:GO

b 执行:  b.[[scope]]    --> 	0:AO(b)
		      				 1:AO(a)
		      				 2:GO
		      				 
c 定义:  c.[[scope]]    --> 	0:AO(b)
		     				 1:AO(a)
		     				 2:GO
		     				 
c 执行: c.[[scope]]    -->   0:AO(c)
		      				 1:AO(b)
		      				 2:AO(a)
		      				 3:GO

现在再来看这句话,函数里边能访问函数外边的变量,但函数外边不能访问函数里边的变量;从上边的过程来看,在b中访问c中的局部变量,是不可能的,因为b.[[scope]](作用域链)中不存在函数c的执行期上下文AO©。c可以访问b和a中的局部变量,因为c.[[scope]](作用域链)中包括函数b和函数a的执行期上下文 AO(b),AO(a)。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值