预编译

预编译发生在何时?

执行全域前一刻,做全域的预编译;执行function前一刻,做function的预编译。


预编译顺序

  1. 宣告形参(形式参数)、
    宣告变数(就是指前面有var let const关键字,注意此时不赋值)
  2. 赋值实参(实际参数)给形参
  3. 宣告function(不管body,执行时才看)
  4. 开始执行(function变数这里才赋值)

实战gogo

console.log(fun(12,26,38))
console.log(fun(167,2))
console.log(`a=${a}`)
var a=1;
function fun(a,b,c,d){
	e=7;
	if(c){}else{c=0}
	return `a(${a}),b(${b}),c(${c}),d(${d})e(${e})`
}

console.log(`a=${a}`)

step1. 在全域执行前一刻,做全域预编译

GO是global object 全局作用域

GO{
	
step1.1 宣告变数  举例:看到 var a=1,定义a为全域变数,但不赋值
	a : undefined,

step1.2 宣告function 注意:宣告function时,不管他的body
	fun : function fun(a,b,c,d){......}
}

step2 全域预编译结束,执行全域执行 - 看一行 执行一行

step2.1 看到console.log(fun(12,26,38)),执行fun function

console.log(fun(12,26,38))
function fun(a,b,c,d){
	e=7;
	if(c){}else{c=0}
	return `a(${a})+b(${b})+c(${c})+d(${d})`
}

step3 揪斗妈爹~~执行fun function的前一刻,做fun function区域预编译

AO是activation object 局部作用域、活跃对象
为甚麽叫活跃对象,是因为function他在跑的时候,AO才存在,function结束,AO消失

step3.1 宣告形参

fun AO{
	a : undefined,
	b : undefined,
	c : undefined,
	d : undefined
}

宣告变数 没有变数宣告
注意:e=7;前面没有var let const关键字,不是需要宣告的变数

step3.2 赋值:实参给形参

fun AO{
	a : 12,
	b : 26,
	c : 38,
	d : undefined
}

step3.3 宣告function fun中没有function需要宣告

step4 function区域预编译结束,执行console.log(fun(12,26,38)) - 看一行 执行一行

step4.1 e=7; 变数的前面没有 var let const,被判定为全域变数
小备注:因为已经在执行阶段,所以变数不用先是undefined再变成7

GO{
	a : undefined,
	fun : function fun(a,b,c,d){......},
	e : 7
}

step4.2 执行完return,AO销毁

step5 执行console.log(fun(167,2)) - 只讲不一样的

GO{
	a : undefined,
	fun : function fun(a,b,c,d){......},
	e : 7
}
fun AO{
	a : 167,
	b : 2,
	c : undefined,
	d : undefined
}

step5.1 if(c){}else{c=0}
因为undefinedfalsy,所以跳到else{c=0}

step5.2 fun执行完,AO销毁

人肉编译器们,剩下三行了,加油

step6 变数提升(hoisting)

console.log(`a=${a}`)
var a=1;
console.log(`a=${a}`)
GO{
	a : undefined,
	fun : function fun(a,b,c,d){......},
	e : 7
}

第一个console.log(a=${a})是在「预编译後,赋值前」,所以a=undefined
第二个console.log(a=${a})是在「赋值後」,所以a=1


提升(Hoisting)

刚刚的「实战gogo」,有看到变数的提升和function的提升。我们稍微总结一下 →

  • 变数的提升:undefined
    原因:取值时,发生在「预编译後,赋值前」
    且因为变数是原始值
  • function的提升:完整的function(不是空壳function)
    原因:发生在「预编译後,执行function时」,
    且因为function是引用值,会去参照function的body

但也不是所有function都会乖乖地提升,那到底是谁怎麽不乖呢?要拜乖乖?


资料来源

【JS深度指南】作用域、作用域链、预编译、闭包基础


<<:  程序精炼唯熟练尔:高阶函式 预设参数 high-order function, default parameter

>>:  [DAY 13] ElastiCache

Day21 ( 高级 ) 戳泡泡 ( 视讯侦测 )

戳泡泡 ( 视讯侦测 ) 教学原文参考:戳泡泡 ( 视讯侦测 ) 这篇文章会介绍,如何在 Scrat...

【Day19】SPI 状态机的实现

SPI是什麽? SPI(Serial Peripheral Interface),是一种同步的传输协...

【Day 13】- 有了这个,就没有打得开的程序了 XD(SetCreateProcessNotifyRoutine)

Agenda 资安宣言 测试环境与工具 技术原理 References 下期预告 资安宣言 撰写本系...

2021-Day1. 开箱 Google Cloud Jam 活动背包

今年参赛的另一个主题,也请大家多多支持,感恩~ https://ithelp.ithome.com...

Day 06 - Google Map 在地向导也是另一种数位足迹

图片来源 延续上一篇最後提到的老照片, 不知道大家认不认为除了FB开地球(开放所有人浏览)之外, ...