25

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


Meils
1.6k 声望157 粉丝

前端开发实践者