函数执行的步骤
- 形成一个私有的执行上下文(AO),然后进栈执行
- 初始化作用域链
- 初始化THIS
- 初始化ARGUMENTS
- 形参赋值
- 变量提升
- 代码执行
- 根据情况决定是否出栈释放
作用域
创建函数的时候就声明了它的作用域,在哪个上下文中创建的,那它作用域就是哪个上下文
作用域和上下文的关系
- 是一个东西,都是函数执行形成的那个空间
- FN的作用域【ECG】ECG 也是全局上下文
- 从核心来说 都是栈内存
- 函数自己执行形成的EC(FN) 上下文
- 函数创建的时候声明了它的作用域
函数执行会形成一个”全新”的”私有”的执行上下文,然后进栈执行
一般情况下,函数执行完,形成的这个私有上下文会出栈释放 来优化内存空间
EC(FN) 私有执行上下文
AO(FN) 私有变量对象 [私有上下文声明的变量都存储在这里=>私有变量]
- AO[active object]是VO的分支,函数私有上下文中[AO]
- 私有变量(AO):
- @1 形参变量
- @2 函数体中声明过的变量
代码执行前的步骤
- 初始作用域链:scope chain <EC(FN),EC(G)>
- 初始化THIS
- 初始ARGUMENTS–实参集合
- 形参赋值
- 变量提升
作用域链
<自己的上下文【执行产生的】,函数的作用域【创建时候声明的】>
<EC(FN),EC(G)>
作用域链机制
1
- 私有上下文中,代码执行阶段,遇到一个变量,我们首先看是否为自己上下文中的私有变量,
- 如果是自己的【AO】,则接下来所有操作,都是操作自己的,和外界的变量没有直接的关系
2
- 如果不是自己私有的变量,则按照作用域链,查找是否为其上级上下文中变量【上级上下文就是函数的作用域】
- 如果找到了,则后期操作的都是上级上下文中的变量
3
- 如果上级上下文也没有这个变量,则继续找其”上上级”上下文,一直到EC(G)全局上下文位置
- 如果全局上下文中也没有
- 获取变量值就是报错
- 设置变量值就是给window设置的属性
练习题
var x = [12, 23];
function fn(x) {
x[0] = 100;
x = [100];
x[1] = 200;
console.log(x); //[100,100]
}
fn(x);
console.log(x); [100,23]
复制代码
console.log(a, b, c);//undefined undefined undefined
var a = 12, //等同于 var a,var b,var c
b = 13,
c = 14;
var fn = function (c) {
console.log(a, b, c);//undefined 13 10
var a = b = c = 20;// c=20,b=20,var a=20
console.log(a, b, c);//20 20 20
};
fn(10);
console.log(a, b, c); //12 20 14
复制代码
如果全局上下文没有变量
获取:报错
赋值:为window变设置属性
/*
/!*
* EC(G)
* VO(G) / GO
* fn ---> 0x000 [[scope]]:EC(G)
*!/
var fn = function () {
/!*
* EC(FN)
* AO(FN)
*
* 作用域链:<EC(FN),EC(G)>
* 形参赋值:--
* 变量提升:--
*!/
console.log(a); //获取的话就是报错 Uncaught ReferenceError: a is not defined
a = 100; //window.a=100
};
fn();
console.log(a, window.a); //100 100
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END