关于作用域与作用域链
函数作用域:
1、什么是函数作用域
- 首先了解js的堆栈内存
1)、栈内存(作用域):
栈内存有两个作用,第一存放基本类型值,第二提供js代码自上而下执行的环境(栈内存销毁,存储的那些j基本类型值也随之销毁)
2)、堆内存:
用来存放引用类型值,比如:对象类型存放键值对、函数类型存放代码字符串(同样堆内存释放,那么引用值也彻底销毁)
- 函数执行
在代码最开始执行时,是代码自上而下执行,执行的是全局代码,所以会形成一个全局上下文EC(GLOBAL),来执行全局代码,全局代码中存在一个变量对象(VO)用来存放全局的变量和对应的值。
代码自上而下执行,执行到函数时,函数每执行一次,就会创建一个全新的执行上下文(可以当作当前函数的私有作用域),然后把执行上下文压进栈内存(ECStack执行环境栈)中去执行,这个执行上下文中存在一个活动对象(AO),用来存储当前上下文中所创建的变量,如果当前上下文中的值没有被外部占用,那么代码执行完后,出栈销毁。
简要来说,私有作用域就是当前函数自己的地盘(自己的执行上下文)用来存放自己的私有变量不受外界影响,私有作用域中变量不被外界访问
2、作用域链
1、什么是作用域链
1、 本质就是指向变量对象的指针列表
2、当代码执行时,会创建变量对象的一个作用域链
3、作用域链的前端,始终都是当前执行的代码所在环境的变量对象
4、作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含环境。这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象。
5、标识符解析,标识符解析是沿着作用域链一级一级地搜索标识符的过程。搜索过程始终从作用域链的前端开始,然后逐级地向后回溯,直至找到标识符为止(比如当前函数执行时 要操作变量a,那么先在自己的作用域中查找,如果找到就使用自己的a,如果找不到就沿着作用域链向上查找,直到找到window全局对象)
这里要注意的是上级作用域如何确定?
如下方事例代码:
//当前函数执行,形成一个私有作用域A,
//A的上级作用域是谁,和他在哪执行的没有关系,
//和他在哪创建(定义)的有关系,在哪创建的,它的上级作用域就是谁
var a = 12;
function fn() {
console.log(a);
}
function sum() {
var a = 120;
fn();
}
sum();//输出 12 而不是 120 这里很容易混淆
(如有错误,请告知)