预编译

108 阅读2分钟

预编译步骤

在script内代码块执行前

  1. 页面产生便创建了GO全局对象(Global Object)(也就是window对象);
  2. 第一个脚本文件加载;
  3. 脚本加载完毕后,分析语法是否合法;
  4. 开始预编译 查找变量声明,作为GO属性,值赋予undefined; 查找函数声明,作为GO属性,值赋予函数体;

在函数执行前

  1. 创建AO对象(Active Object)
  2. 查找函数形参及函数内变量声明,形参名及变量名作为AO对象的属性,值为undefined
  3. 实参形参相统一,实参值赋给形参
  4. 查找函数声明,函数名作为AO对象的属性,值为函数引用

题目

题目一

var bb = 1;
function aa(bb){
    bb = 2
    alert(bb)
}
aa(bb)
alert(bb)
// 答案
2 1

注释

在函数体内, bb并没有使用var来定义, 按理说这个bb在预处理的时候应该是window的属性. 但在这里, 函数声明的时候, 带了一个参数bb, 也就是相当于在函数体内声明了var bb. 所以, 函数里的bb就是函数活动对象的属性. 所以, 函数里的bb就是函数活动对象(OA)的属性. 所以函数执行时会输出2. 函数执行完后, 函数的活动对象被销毁, 也就是这个局部的这个bb被删除了, 执行流进入到window, 再输出bb, 值就是1了

var bb2 = 1;
function aa2(tt) {
  bb2 = 2
  console.log(bb2)  //2
}
aa2(bb2)
console.log(bb2)  //2

题目二

//原来的代码
var a = 1;
function test(){
    // console.log(a) 位置A
   class a {}
   // console.log(a) 位置B
}
test()

//实际上提升后的
var a = 1;
funciotn test(){
    console.log(a) 位置A  // 在test() 作用域内找得到a, 是一个class但是存在TDZ暂时性死区, 访问错误
    class a {}
    console.log(a) 位置B // a已经声明出来了
}

//答案
报错 
class a{}