JS中的作用域及作用域链
1.作用域
作用域(scope)指的是变量存在的范围。在 ES5 的规范中,Javascript 只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。ES6 又新增了块级作用域,暂时不提及。
全局作用域
全局作用域中的对象可以在代码的任何地方访问,一般来说,下面情况的对象会在全局作用域中:
- 最外层函数和在最外层函数外面定义的变量
- 没有通过关键字”var”声明的变量
- 浏览器中,window对象的属性
局部作用域(又称为函数作用域)
所有的变量和函数只能在作用域内部使用。
2.作用域链
在理解作用域链前,我们要先知道执行上下文,变量对象与活动对象这些概念。
- 执行上下文
每次当控制器转到可执行代码的时候,就会进入一个执行上下文。执行上下文可以理解为当前代码的执行环境,它会形成一个作用域。
一个执行上下文的生命周期可分为创建阶段和代码执行阶段。
执行上下文生命周期
-
变量对象
-
活动对象
变量对象在进入执行阶段时,就变成了活动对象。
上面说了一些概念后,我们知道一个函数在被调用时,会创建一个执行上下文,在执行上下文的生命周期这个过程中,生成了变量对象,建立了作用域链,确定了this方向,那么,作用域链到底应该怎么理解。
作用域链,是由当前环境与上层环境的一系列变量对象组成,它保证了当前执行环境对符合访问权限的变量和函数的有序访问。
例子:
function a(x,y){
var b=x+y;
return b;
}
a(5,10);
当执行函数a时,就进入了函数a的执行上下文,这时候函数a的作用域链如下:
在这里面,函数的活动对象是它的作用域链里的第一个对象,第二个对象就是包含函数的环境,在这里是全局对象。
注意:
作用域链的非自己部分在函数对象被建立(函数声明、函数表达式)的时候建立,而不需要等到执行;
作用域链的前面部分是静态的,所有函数共享同一个链,当函数执行时,建立一个自己当次执行的作用域,然后把这个作用域与前面共享的链关联
起来;
[[Scope]]是在函数创建的时候保存起来的----静态的(不变的),只有一次并且一直都存在--直到函数销毁.[[Scope]]与Scope(作用域链)是不同的,前者是函数的属性,后者是上下文的属性.
在函数运行过程中标识符的解析是沿着作用域链一级一级搜索的过程,从第一个对象开始,逐级向后回溯,直到找到同名标识符为止,找到后不再继续遍历,找不到就报错。
3.总结
- 函数在执行过程中,先从自己内部的作用域中寻找用到的变量;
- 如果没有找到,则从创建当前函数所在的作用域中寻找,以此类推,一级一级寻找,知道找到为止;