作用域和作用域链 精解

作用域(scope):一个变量的可用范围

2种:
全局作用域 :任何地方都可以访问,反复使用

函数作用域(局部作用域):仅在函数内部可访问,不能反复使用
例子:

var a=10;
	function fun()
	{
		var a=100;
		a++;
		console.log(a);
	}
	fun();//101

	console.log(a);//10

函数的生命周期

作用域前言
每个函数都有自己的执行环境,(首先,所有的环境会形成 一个环境栈)。当代码执行进入一个函数后(也就是开始执行函数里的代码了),函数的执行环境会被推进(push)这个大的环境栈中,当函数执行完成后,大的环境栈就会将该函数的环境栈挤出(pop),并将控制权交还给原先的执行环境,就是在回到原来的执行流上去了。

当代码在执行环境中执行时,变量对象的作用域链就被创建了。作用域链的目的就是为执行环境有权访问的变量和函数提供有序的访问,不让其乱套。有顺序的来。作用域链的前端(或最接近的,最里面的,最里层的)始终都是当前正在执行的代码所在的执行环境的变量对象。

如果执行环境是函数,则将其活动对象(activation object)简称:AO 作为变量对象。活动对象最开始只包含一个变量,arguments对象(在全局环境中不存在)。这就是该函数的作用域链上最前端的,最里面的了,该作用域链上下一个变量对象就是来自于包含(即外部)环境,再下一个也是来自再下一个外部环境,一层一层的逐渐的往外剥皮,知道最外面的全局环境。全局环境的变量对象就是该作用域链上最后一个对象了。

注释:’‘函数的作用域链上最前端的,最里面’'指的是预编译将全局对象中的声明和函数(执行函数列表参数,声明变量,函数内部嵌套的函数)提升到最上方,从上至下执行。-----可以百度参考变量提升和函数提升,或js预编译

1、开始执行前
1-1 创建执行环境栈(ECS数组):临时保存正在执行的函数的环境
1-2 向执行环境栈中加入第一个默认函数main()
1-3.创建全局作用域对象window

2、定义函数时
2-1.创建函数对象,封装定义
2-2. 声明函数名变量,引用函数对象
2-3. 函数对象的scope属性引用回,创建函数时的作用域

在这里插入图片描述
3、调用函数时
3-1 ESC中加入一个新的元素(执行环境),记录新函数调用
3-2 创建一个活动对象,保存本次函数调用用到的局部变量
3-3 ESC新执行环境元素,引用活动对象
3-4 活动对象中的parent属性引用函数的scope指向的父级作用域对象
3-5 在执行过程中:优先使用活动对象中的局部变量
3-6 局部中没有,才延parent向父级作用域找*
在这里插入图片描述
** 4、调用函数后
4-1 执行环境栈中本次函数的执行环境出栈
4-2 导致活动对象被释放 导致局部变量一同释放

在这里插入图片描述

作用域链

作用域链*:由多级作用域连续引用形成的链式结果
掌管一切变量的使用顺序: 先在局部找,没有,就延作用域向父级作用域找

在JavaScript中,函数也是对象,实际上,JavaScript里一切都是对象。函数对象和其它对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性。其中一个内部属性是[[Scope]],该内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问。

当一个函数创建后,它实际上保存一个作用域链,并且作用域链会被创建此函数的作用域中可访问的数据对象填充。例如定义下面这样一个函数:

function func() {
var num = 1;
alert(num);
}
func();

在函数func创建时,它的作用域链中会填入一个全局对象,该全局对象包含了所有全局变量,如下图所示(注意:图片只例举了全部变量中的一部分):

在这里插入图片描述

执行此函数时会创建一个称为“运行期上下文(execution context)”(有人称为运行环境)的内部对象,运行期上下文定义了函数执行时的环境。每个运行期上下文都有自己的作用域链,用于标识符解析,当运行期上下文被创建时,而它的作用域链初始化为当前运行函数的[[Scope]]所包含的对象。

这些值按照它们出现在函数中的顺序被复制到运行期上下文的作用域链中。它们共同组成了一个新的对象,叫“活动对象(activation object)”,该对象包含了函数的所有局部变量、命名参数、参数集合以及this,然后此对象会被推入作用域链的前端,当运行期上下文被销毁,活动对象也随之销毁。新的作用域链如下图所示:
在这里插入图片描述
外部环境不能访问内部环境的任何变量和函数。即可以向上搜索,但不可以向下搜索。

可以理解为什么有关于作用域链的定义说,作用域链是一群对象,或者对象列表(链表)。也有总结如下:

对于javascript最顶层的代码(不包含任何函数定义内的代码),其作用域链只包含一个对象:即全局对象。
对于不包含嵌套函数的函数,其作用域链包含两个对象:其自身的变量对象和全局变量对象。
对于包含了嵌套函数的函数,其作用域包含至少三个对象:自身的变量对象,外层的(将自身嵌套的),全局变量对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值