听小野森森的预编译,收货颇丰,之前完全没有了解过。遇到这方面的面试题,特别的头大,只知道变量和函数会提升。这次终于了解了捕鱼的技术,而不是鱼。但是现在很少用var了,基本上都是用const、let了,乐趣少了些,哈哈哈。

JavaScript 在执行脚本的时候,首先会通篇的检查是否有语法错误,如果有,报错,不再继续执行;当没有语法错误时,则进行预编译,最后解释一行执行一行。

声明提升

  • 函数声明整体会被提升,函数内部的代码不会进行预编译,函数执行的前一步时,才会对函数内部的代码进行预编译

函数 test 被提升到顶部,所以函数可以在其声明之前被调用

test();

function test(){
  console.log('test');
}
  • var 声明的变量会被提升,只会提升变量名,运行到赋值那一行才会进行赋值,声明的变量挂载到当前的作用域下
  • 非 var 声明的变量,是赋值语句,如果当前作用域下没有声明过该变量(函数声明或者形参),则挂载在window对象上

var 声明的变量a会被提升到顶部,值为 undefined,运行到赋值那一行,它的值才是100。变量 b 不会被提升,赋值之前使用 b 报错,赋值之后则不会。

// console.log(a, b);
console.log(a);

var a = 100;

b = 200;

console.log(a, b);

函数内部声明的变量 b 保存在当前作用域内,当前作用域下没有声明过变量 c , 则挂载在 window 对象上。

function test() {
  var b = 20;
  c = 20
}

test();

console.log(c);

函数内部通过形参声明变量

function test(c) {
  var b = 20;
  c = 20
  console.log(c);  // 20
}

test();

console.log(c); // Uncaught ReferenceError: c is not defined

通过函数声明的方式声明变量

function test(c) {
  var b = 20;
  c = 20
  function c() { };
  console.log(c);  // 20
}

test();

console.log(c); // Uncaught ReferenceError: c is not defined

AO对象

当函数执行的前一步时,JavaScript引擎才会对函数进行预编译,会创建AO对象, Activation Object 也就是函数上下文对象。

具体过程

function test(a){
  console.log(a);  //func a
  var a = 1;
  console.log(a);   // 1
  function a(){};
  console.log(a);  // a
  var b = function(){};
  console.log(b);  // func b
  function d(){};
}

test(100);
  • 第一步、创建AO对象,就是一个{};
AO = {}
  • 第二步,寻找形参和var变量声明
AO = {
  a: undefined 
  b: undefined
}
  • 第三步,把实参赋值给形参
AO = {
  a: 100 
  b: undefined
}
  • 第四步,寻找函数声明
AO = {
  a: function a(){},
  b: undefined,
  d: function d(){};
}
  • 第五步,执行函数,忽略var 声明和函数声明,遇到赋值语句,会覆盖初始化值
AO = {
  a: function a(){},
  b: function(){},
  d: function d(){};
}

GO对象

GO 对象就是 Global Object 全局上下文,和 AO 对象类型。

分析具体过程

var a = 100;

function a(){
  console.log(2);
}
  • 第一步、创建 GO 对象
GO = {}
  • 第二部、寻找变量声明
AO = {
  a: undefined
}
  • 第三步、寻找函数声明
AO = {
  a: function a(){}
}
  • 第四步、执行语句、遇到赋值语句,会覆盖初始化值

面试题

function test(a,b){
    console.log(a);  // 1
    c = 0;  
    var c ;
    a = 5;
    b = 6;
    console.log(b); // 6
    function b(){};
    function d(){}
    console.log(b); // 6
}

test(1);

具体过程

GO = {
  test: function test(){},
}

// test函数执行

// 寻找形参、变量声明
AO = {
  a: undefined,
  b: undefined,
  c: undefined,
}

// 实参赋值给形参
AO = {
  a: 1,
  b: undefined,
  c: undefined,
}

// 寻找函数声明
AO = {
  a: 1,
  b: function b(){},
  c: undefined,
  d: function d(){},
}

// 执行代码,赋值

itimestamp
3 声望0 粉丝