js的作用域链

本文详细解析了JavaScript中执行期上下文的概念,包括AO对象、函数执行环境、[[scopes]]作用域链,通过实例展示了不同场景下的作用域链变化。理解这些有助于开发者更准确地定位变量和控制代码执行流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.概念

执行期上下文:当函数执行时,会创建一个称为执行期上下文的内部对象 (保存函数的作用域)

上文成员(js语法可以直接访问的成员)

下文成员(底层语法访问的成员 仅供js引擎存取) 如[[scopes]] 

  • 一个执行期上下文定义了一个函数执行时的环境
  • 每次调用函数创建的执行上下文不同
  • 当函数执行完毕,它所产生的执行上下文被 "销毁"

执行期上下文指的就是函数执行前一刻所产生的AO对象
函数执行环境就是指变量提升函数提升得到的那些AO对象属性
function fn() {    }

函数多次调用,产生不同的AO对象:
fn();            ---->AO{}
fn();            ---->AO{}
函数执行完毕之后对应的AO对象销毁

[[scopes]] :指的是作用域  保存了运行期上下文的集合

  • 函数生成了就会有个属性 [[scopes]]  作用域“数组” (只能引擎使用)
  • 函数调用时生成AO的对象就保存在[[scopes]]对象内部的顶层
  • 函数在定义/声明时就有[[scopes]]  里面保存的是这个函数上层的AO对象

作用域链:[[scope]]中所保存的执行期上下文对象的集合 集合呈链式连接

2.作用域链

示例1:

function fn(b) {
    var a = 20
    function fm() {
    }
}
//调用一次就有一个AO对象生成
fn(100) //AO{a:20,b:100,fm:}
fn(200) //AO{a:20,b:200,fm:}

如图:

 示例2:

function fn() {
    var a = 30
    function fm() {
        var b = 20
        console.log(a)
    }
    fm()
    fm()
}
fn()
fn()

如图:

示例3: 

function fn(a) {
    function fm() {
        var b = 20
        console.log(a)
    }
    fm()
    fm()
}
fn(100)
fn(200)

如图:

 示例4:

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执行了才会产生c的定义

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

 示例5:

function a() {
	var aaa = 123;
	function b() {
		var bbb = 234;
		console.log(aaa);
	}
	return b;
}
var glob = 100;
var demo = a();
demo();
/*
 Go:{a函数,glob:100,demo:a.[[scopes对象里面的,b函数]]}
 a.[[scopes]]==>[AO:{aaa:123,b函数,},Go]
 b函数.[[scopes]]==>[,a.[[scopes]]]<====>[AO(b):{bbb:234,打印aaa},AO(a):{aaa:123,b函数,},Go]
 demo() 
*/

  执行的作用域链:

a 定义:  a.[[scope]]    -->     0:GO==>{a函数,glob:100,demo:a.[[scopes对象里面的b函数]]}

a 执行:  a.[[scope]]    -->     0:AO(a)==>{aaa:123,b函数}
                                           1:GO
                               
b 定义:  b.[[scope]]    -->     0:AO(a)
                                           1:GO


b 执行:  b.[[scope]]    -->     0:AO(b)==>{bbb:234,打印aaa}
                                           1:AO(a)
                                           2:GO
 demo(): GO中找到==>a的作用域==>调用b函数==>b的作用域                      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

哈哈ha~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值