js深刻理解--解析与执行过程

2019-04-09  本文已影响0人  朝西的生活

全局预处理阶段

在js代码真正执行之前, 编译器会先对代码执行预处理, 看下面例子


console.log(a); // undefined
console.log(b); // ReferenceError: b is not defined
console.log(c); // undefined
console.log(d); // Function

var a = 1;
b = 2;
var c = () => {
  alert(1);
}
function d(){
  alert(2);
}

可以看到, 上面结果实际与我们预期差距很大, 那么编译器是如何进行js的预处理的呢

  1. 创建词法作用域(可以理解为一个js代码执行前就存在的全局变量)
  2. 扫描全局作用域下所有使用 var 关键字声明的变量, 将其赋值为 undefined;
  3. 扫描全局作用域下所有使用 函数声明 方式声明的函数, 并将其赋值为对该函数的引用

这一操作被称为 声明提前 或者 声明前置 全局的预处理完成后, js代码开始正常执行

这里面还是有很坑的地方

console.log(a); // ReferenceError: b is not defined
const a = 1;
var a = 1;
function b(){
  var c = 2;
}

// 此时的GO对象
{
  a: undefined,
  b: Function
}
// b函数内声明的c变量没有被预处理
a(); // 1
b(); // ReferenceError: b is not defined
c(); // ReferenceError: b is not defined
d(); // ReferenceError: b is not defined
e(); // ReferenceError: b is not defined
f(); // ReferenceError: b is not defined

function a(){
  console.log(1);
}
const b = function(){
  console.log(2);
}

(function c(){
  console.log(3);
})();

const d = new Function('console.log(4)');
a(); // 2
console.log(b); // undefined
function a(){
  console.log(1);
}
function a(){
  console.log(2);
}

var b = 3;
var b = 4;
// a未声明, undefined, 不会报错
if (typeof a !== 'undefined'){
  // do something
}

但是当es6的块级作用于出现之后, typeof也不安全了

typeof a; // ReferenceError: a is not defined
let a = 1;

函数预处理阶段

我们知道, 在块级作用域出现之前, js一直都是函数作用域, 类似的, 函数在真正执行之前也会经历一个预处理阶段

  1. 创建一个AO对象
  2. 找出函数形参以及函数作用域内的变量声明, 并赋值为undefined
  3. 将形参与实参的值相统一
  4. 找出作用域内所有的函数声明, 复制为其函数的引用

与全局预处理不同, 函数的预处理阶段多了对函数参数的处理

上一篇下一篇

猜你喜欢

热点阅读