JavaScript的作用域链的理解

如果将一个局部变量看做是自定义实现的对象的属性的话,那么可以换个角度来解读变量作用域。每一段代码都有一个与之相关联的作用域链。下面举例来理解作用域链(一个页面的作用域链可以看成一棵树)。

var  global_var = "global"; // 第1步
function test(x){ 
	var y = 0;
	return x+y;
} //第2步
test();//第3步
test();//第4步
function checkscope(){
	var scope = "local scope";
	function nested(){ //嵌套函数的定义,我的理解是在外部函数调用时才定义。每次调用都会定义一次,没调用时就没定义。
		var scope = "nested scope";
		return scope;
	}
	return nested();//第7步
}//第5步
checkscope();//第6步,返回的结果是 nested scope



下面逐步分析作用域链的变化。

0. 初始化创建作用域链的第一个结点,即树T的根节点,名为window的结点。

第1步,.定义一个全局变量后(var  global_var),树T在window结点下添加一个孩子结点global_var。

第2步,定义函数test后,树T在window结点下添加一个孩子结点test。

第3步, 调用test函数时,会创建一个新对象(该对象不可见,内部实现)来存储它的局部变量。假设创建的对象名称为_test_obj_1。那么树T需要在window结点下添加孩子结点_test_obj_1。并且_test_obj_1结点有2个孩子x和y。(当test执行完成后,垃圾自动回收功能会自动释放_test_obj_1对象,不一定是立即释放)

第4步,再次调用test函数,会创建一个新对象。对象名称假设是_test_obj_2。那么树T需要在window结点下添加孩子结点_test_obj_2。并且_test_obj_2结点有2个孩子x和y。(当test执行完成后,垃圾自动回收功能会自动释放_test_obj_2对象,不一定是立即释放)

第5步,定义了一个嵌套函数。树T在window结点下添加一个孩子结点checkscope。

第6步,调用嵌套函数的外部函数checkscope时。会创建一个新对象,假设名称是_checkscope_obj_1。window结点下添加孩子_checkscope_obj_1。此时会定义函数nested。_checkscope_obj_1结点下添加2个孩子nested和scope。

第7步,调用嵌套函数nested时。会创建一个新对象,假设名称是_nested_obj_1。树T在_checkscope_obj_1结点下添加一个孩子结点_nested_obj_1和scope。

每次调用外部函数checkscope时,内部函数都回重新定义一遍。每次调用外部函数时作用域链是不同的。如上面test函数调用了2次生成_test_obj_1和_test_obj_2。

ps:_nested_obj_1对象应该还有个nested结点和scope结点。

scope结点被nested定义的scope给覆盖了。

如果不nested不定义scope,其实也可以直接访问scope,其值是"local scope"。


作用域链如下图:



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值