js的解析与执行过程
alert(a);
function a(){ alter(2); }
alert(a);
var a = 1
alert(a);
var a = 3;
alert(a);
function a(){ alter(4); }
alert(a);
a();
- 第一个 alert(a) 弹出 function a(){ alter(4); } 函数体
- 第二个 alter(a) 弹出 function a(){ alter(4); } 函数体
- 第三个 alter(a) 弹出 1
- 第四个 alter(a) 弹出 3
- 第五个 alter(a) 弹出 3
- 最后一行报错 a is not a function
- 执行分析
// 第1行,没有关键字 , 不解析
// 第2行,遇到 function 关键字,解析到全局的头部
a = function a(){ alter(2); }
// 第3行,没有关键字 , 不解析
// 第4行,遇到关键字 var , 解析到全局的头部
a = undefined
// 第5行,没有关键字 , 不解析
// 第6行,遇到关键字 var , 解析到全局的头部
a = undefined
// 第8行,遇到 function 关键字,解析到全局的头部
a = function a(){ alter(4); }
// 第9行,没有关键字 , 不解析
// 第10行,a() 函数调用
此时这里有4个同名变量 a ,依循规则是:function 优先与 var, 同名的后面覆盖前面的
因此,a = function a(){ alter(2); } 替换掉下面的2个 a = undefined ,a = function a(){ alter(4); } 又替换掉 a = function a(){ alter(2); } ,最终只剩下 a = function a(){ alter(4); }
接下来我们进入正题哦
一、 全局预处理和执行
1.1、全局预处理阶段
实例0
var a = 5;
var b ;
function xxx(){
// 用声明的方式创建的函数
}
var fun = function () {
// 用函数表达式创建的函数
}
c = 5; // 不会报错,但是也不会加入词法环境
假设全局我们创建了上诉的内容
- 首先js会创建一个词法环境对象
LexicalEnviroment
,全局下等同于我们的window
;
// 创建词法环境如下
LexicalEnviroment{
a: undefined
b: undefined
xxx: 该函数的引用
fun: undefined
}
// 这里有着变量提升的知识
实例1
f(); // ff
g(); // 报错: g is not a function
function f(){
console.log('ff');
}
var g = function() {
//
}
// 【解析】
// 因为词法环境中f存在引用,g确实是undefined,因此当在为g赋值之前调用g会报错。
实例2
console.log(a); // undefined
console.log(b); // 报错: b is not defined
var a = 1;
b = 4;
实例3 变量重名
// 处理函数声明冲突 => 覆盖
alert(f);
var f = 0;
function f() {
cosole.log('f');
}
// 执行结果: 弹出一个f函数的字符串
// 处理变量声明冲突 => 忽略
alert(f);
function f() {
cosole.log('f');
}
var f = 0;
// 执行结果: 弹出一个f函数的字符串
// 【解析】
// 可见不是根据最后出现的覆盖前面的
1.2、全局执行阶段
实例 4
alert(a);
alert(b);
alert(f);
alert(g);
var a = 5;
b = 6;
alert(b);
function f() {
console.log('f');
}
var g = function () {
console.log('g);
}
alert(g);
- 执行过程如下
1. 构建词法环境
2. 词法环境如下
{
f: function () {console.log('f')}
a: undefined
g: undefined
}
3. 开始执行
4. alert(a); // undefined
5. alert(b); // 报错: b is not defined
6. alert(f); // function () {console.log('f')}
7. alert(g); // undefined
8. a = 5; b = 6 [window下的变量赋值]
9. alert(b); // 6
10. g = function () {console.log('g);} [window下的变量赋值]
11. alert(g); // function () {console.log('g);}
// 最后的词法环境如下(window)
{
f: function () {console.log('f')}
a: 5
g: function () {console.log('g);}
b: 6
}
二、 函数预处理和执行
2.1、函数预处理阶段 + 执行阶段
实例 5
function f(a, b) {
alert(a);
alert(b);
var b = 10;
function a() {
//
}
}
f(1,2);
- 执行分析
1. 1. 构建词法环境
2. 词法环境如下
{
a: 最初是1, 因为冲突,最后变成了 函数的引用 function a() {// }
b: 2
}
3. 开始执行
4. alert(a); // function a() {// }
5. alert(b); // 2
实例 6
- 函数内部如果没有用var声明的变量,会成为最外部的词法环境的变量(也就是全局了)
function a() {
function b() {
c = 100;
}
b();
}
a();
// window.c === 100
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。