JavaScript预编译

预编译前奏

  • 变量声明提升
    • 通过var定义(声明)的变量,在定义语句之前就可以访问到
    • 值:undefined
  • 函数声明提升
    • 通过function声明的函数,在之前就可以直接调用
    • 值:函数定义(对象)
  • imply global 暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量就为全局对象所有
//赋值都是自右向左,所以b是未经声明的变量,归window所有
function test() {
  var a = b = 123
}
test()
console.log(window.b) //123
console.log(window.a) //undefined
  • 一切声明的全局变量,全是window的属性

预编译

  • 在全局代码执行前,js引擎会创建一个栈来存储管理所有的执行上下文对象
  • 预编译发生在函数执行的前一刻
function fn(a) {
  console.log(a) //function a() {}
  var a = 123
  console.log(a) //123  此时变量已经提升,a会被新赋值为123
  function a() {}
  console.log(a) //123 function a() {}已经被提升
  var b = function() {}
  console.log(b) //function b() {} var b已经被提升,b被新赋值为function
  function d() {} 
}
fn(1)
  • 预编译过程中做的事情:
    1.创建AO(Activation Object)(执行期上下文)
    2.找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
    AO{
    a :undefined
    b :undefined
    }
    3.将实参和形参相统一
    AO{
    a :1
    b :undefined
    }
    4.找函数体内的函数声明
    AO{
    a :function a() {}
    b :undefined
    d :function d() {}
    }
    以上这些都是预编译之前做的事情,所以第一次打印a是个function,后期赋值操作是在编译时期做的,要分清。

例子1

function test(a,b) {
  console.log(a) //1
  c = 0
  var c
  a = 3
  b = 2
  console.log(b) //2
  function b() {}
  function d() {}
  console.log(b) //2
}
// test(1)
// AO {                  
//   a : undefined,
//   b : undefined,
//   c : undefined
// }
// -->
// AO {
//   a : 1,
//   b : function,
//   c : undefined,
//   d : function
// }
// 到执行的时候:
// AO {
//   a : 3,
//   b : 2,
//   c : 0,
//   d : function
// }

例子2

function test() {
  console.log(a) //function
  console.log(b) //undefined
  var b = 234
  console.log(b) //234
  a = 123
  console.log(a) //123
  function a() {}
  var a
  b = 234
  var b = function() {}
  console.log(a) //123
  console.log(b) //function
}
test(1)
// 预执行:
// AO {
//   a : undefined,
//   b : undefined
// }
// -->
// AO {
//   a : 1,
//   b : undefined
// }
// -->
// AO {
//   a : function
//   b : undefined
// }

注:

  • 在全局声明时与在函数体声明的原理一样,但是少了实参与形参相统一的步骤。
  • 函数体生成的是AO对象,而全局生成的是GO对象(Global Object)(GO === window)。
console.log(test) //function
function test(test) {
  console.log(test) //function
  var test = 234
  console.log(test) //234
  function test() {}
}
  • 自己作用域内有自己的变量先寻自己的(就近原则)
function fn() {
  console.log(global) //undefined
  global = 200
  console.log(global) // 200
  var global = 300
}
fn()
var global
// GO {
//   global : 100
// }
// AO {
//   global : undefined
// }
// -->
// AO {
//   global : 200
// }
  • 预编译时是不会看条件判断等语句,依然会变量声明提升
function test() {
  console.log(b) //undefined
  if(a) {
    var b = 100
  }
  console.log(b) //undefined
  console.log(c) //234
}
var a
test()
a = 10
console.log(c) //234
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容