执行上下文 ES3
每个函数执行的时候都会产生执行上下文 执行上下文是一个对象,里面包含有变量对象(当前函数的变量 VO),其中全局的 VO 又称 GO (全局的 GO 可以在任何地方访问), 【但是执行上下文的 VO 我们不能访问的,主要是为了保护变量不能随意修改】 当前执行上下文的 VO 又称为 AO
执行上下文栈——调用栈——执行栈 Call Stack
调用栈也称为执行栈,也就是执行上下文栈,在函数执行的时候生成(每次函数执行都会产生一个) 栈低是全局执行上下文,栈顶是当前函数执行上下文 栈是一种数据结构,里面放有很多执行上下文栈
作用域链 scopeChain
scope 是在函数创建的时候生成的,跟在哪里执行没有关系 执行上下文,内部不仅有 VO, this, 还有 scope 一个变量定义会现在本局域块内查找,找不到向父级作用域块查找,直到找到全局 gobal,未找到报错
阶段
执行上下文有两个阶段
编译阶段 函数在创建阶段会被赋值,而变量是 undefined,遇到变量重名不会覆盖,let 不会放在 vo 里
执行阶段 执行阶段给变量进行赋值
作用域链
function two() {
console.log(a);
}
function one() {
var a = 2;
two();
}
var a = 1;
one();
// -----
// 1
let globalEC = {
vo: {
one: () => {},
rwo: () => {},
a: 1,
},
};
- 优先级 函数声明 > arguments > 函数声明
function sum(a, b) {
function a() {
console.log(1);
}
var a = function () {
console.log(2);
};
a();
}
sum(1, 2);
// 打印2
function sum(a, b) {
var a = function () {
console.log(2);
};
function a() {
console.log(1);
}
a();
}
sum(1, 2); // 打印2
function sum(a, b) {
a();
var a = function () {
console.log(2);
};
function a() {
console.log(1);
}
}
sum(1, 2); // 打印1
a();
function a() {
console.log(1);
}
var a = function () {
console.log(2);
};
a();
// 输出 1 2
暂时性死区
在代码块内,使用 let 和 const 命令声明变量之前,该变量都是不可用的,语法上被称为暂时性死区。
let a = 1;
function test() {
console.log(a);
let a = 2;
}
严格模式 use strict
非严格模式下是 window global, 严格模式下 undefined
--- 豪华分割线 ----- --- 豪华分割线 ----- --- 豪华分割线 ----- --- 豪华分割线 ----- --- 豪华分割线 -----
词法作用域
variableEnvironment laxicalEnvironment
let 声明变量会放到 词法环境中,其中一个 {} 为一个块,遇到一个 {} 创建一个词法作用域
词法环境
可执行代码类型
- 全局代码、eval、函数 会创建新的执行上下文,执行上下文又叫执行环境 Execution Context
- 一个执行上下文中包含多个词法环境
词法环境 laxicalEnvironment
ES6 没出来之前 词法环境=变量环境
放 let const 声明的变量 和 函数
创建:全局函数、函数声明、whit、 try catch,类似代码执行的时候有词法环境
构成:环境记录项+outer(可能外空的外部词法环境)
变量环境 variableEnvironment
- 放 var 声明的变量
环境记录项
- 都是记录环境里面的变量
- 声明式环境记录项
var a = 1;
var b = 3;
function test() {}
- 对象式环境记录项
var whileObj = { a: 1, b: 2 };
with (whileObj) {
console.log(a, b);
}
执行环境 & 执行上下文 Execution Context
- 代码执行的时候创建,执行栈 ECStack
- 一个函数执行,只有一个变量环境,但是有多个词法环境,词法环境在执行的时候可能发生变化
- 变量环境组件永远不变,词法环境组件有可能变
函数作用域 scope
- 函数创建的时候, 会确定它的作用域,指向当前创建的词法环境(需要 outer,形成作用域链)
- 它本质是,执行上下文中的词法环境或者变量环境对象
- 函数形参直接赋值,本身就在顶部
其他
- 编译阶段:分词、词法解析、ast、确定作用域
- 静态作用域,创建的时候决定,跟在哪执行没关系