预编译 - 变数和function的被建立、初始化/预编译、执行的全纪录

你以为JS拿来就乖乖照着我们打的一行一行跑吗?太天真了,我说我~~
变数怎麽存,存哪里,在哪里叫得到变数出来?我们会连续几天,讨论这个问题~

预编译

一句话解释,预编译是干蛤的?
根据宣告变数、宣告function的关键字,在内存开辟位置给变数、function

预编译发生在何时?

执行前一刻,做预编译:

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

function scope内部的预编译的编译顺序

  1. 建立形参(形式参数)、
    建立变数

    特别注意:形参var 初始化undefined;letconst没有初始化

  2. 赋值实参(实际参数)给形参

  3. 建立function(此时不管function的body是甚麽,执行时才看)

  4. 开始执行(function变数这里才赋值)

巢状function的建立、预编译、执行 Rundown - 是不是很像俄罗斯娃娃

ornament-g86a0c122a_1920.jpg

图片作者:https://pixabay.com/zh/users/schwoaze-4023294/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=3131097"

各functionScope预编译的时间轴.png

function outerFun(){
	function innerFun(){};
	innterFun();
};
outerFun();
  • window object在预编译的step4:宣告function时,建立了outerFun
  • window object执行
  • window object执行中,执行到outerFun()时:
    • 执行outerFun代码的前一刻,预编译outerFun
      • 预编译outerFun时,建立了innerFun
    • outerFun执行
    • outerFun执行中,执行到innerFun()时:
      • 执行innerFun代码的前一刻,预编译innerFun
      • innerFun执行

整理一下逻辑:

  • 预编译发生在执行之前
  • 预编译时会建立变数、function

试问:执行时,我爱多早呼叫变数、呼叫function,爱多早就多早,不会报错,顶多undefined?
是的呀~~因为我已经把宣告变数、宣告function这件事情,提升了嘛~

提升(Hoisting)

(这里也还不是提升的完整版
受限於let有一丢丢的麻烦,这里只先讨论var变数和function
一定会有完整版的放心~~)

  • var变数的提升:undefined

    • 取值时,发生在「变数本人被建立,初始undefined後,赋值前」
    • var的预编译有初始化undefined

    →故:var变数的提升,得undefined

  • function的提升:完整的function(不是空壳function)

    • 发生在「function本人被建立,(执行function前必须的)预编译完成之後」
      换句话说就是「function执行时」
      从「要呼叫function,function一定正在执行阿~」的观点也很合理
  • 小整理:var变数、function甚麽时後有值的(可以往上对照俄罗斯娃娃那里)

    • var要撇除stack内存的初始值(undefined),须等到有人对他赋值
    • function
      • 建立时,stack内存的值,由heap内存提供function的地址
      • function要有内变数、内层function,须等到function自己进行预编译时

内存stack and heap.png

猜猜:是不是用原始值引用值来区分能不能完整提升?

.

.

.

.

.

.

想多了(我就是这样误以为)

object,array都是引用值的一种,但他们就不像function object可以整块完整被提升。

console.dir(o) //undefined
console.dir(b) //undefined
console.dir(f) //f()
var o={
    'name':'小o',
    '白花':'可曾枯萎呀'
}
var b=['轻声唱着','少年的模样','会悲伤会幻想']
function f(){
    var name='别去打扰她'
}

//部分歌词:<<旅行家说>> 毛不易 

至於为甚麽只有function可以有这个好康,平平都是引用值,为甚麽object和array没有呢?
我个人的想像是,因为var变数的作用域(有效范围)是以function为界,所以才会以function做为单位进行提升。

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

function 预编译:函数声明 vs 函数表达式

fun1();  //1
fun2();  //Uncaught TypeError: fun2 is not a function

//function声明
function fun1(){console.log(1)};
//function表达式
var fun2=function(){console.log(2)}; 

function表达式虽然提升失败,被说fun2不是一个function不被承认QQ
但并没有破坏规则,规则还是原本那个规则喔~~来,上原因

GO{
	fun1 : function fun1(){......},
	fun2 : undefined
}

没错,因为他电脑看到var fun2=,就觉得他是一个原始值,不是function引用值
殊不知後面等於一个function。失算失算

小结论:能不能像function宣告完整被提升的关键因素,是function关键字


<<:  人脸辨识-day20 资料预处理--1

>>:  Swift纯Code之旅 Day25. 「各个TableViewHeader下的Cell显示(2)」

前端工程师也能开发全端网页:挑战 30 天用 React 加上 Firebase 打造社群网站|Day7 处理注册登入的细节

连续 30 天不中断每天上传一支教学影片,教你如何用 React 加上 Firebase 打造社群...

【图解演算法教学】二元树的一生,听说有些凄凉!?

Youtube连结:https://bit.ly/3mTlgpQ 软件世界中「树」长得跟现实生活中...

[ Day 35 ] - Electron 应用程序 - 更新自动化 ( 说明篇 )

已经打包拿到客户那的 Electron 应用程序 , 如果有 BUG 需要更新时该怎麽办呢 ? 一般...

[Day 14] - 初探永丰银行线上收款API - 丰收款 - HASH ID计算(1)

接续昨天 根据规格书,我们要用永丰提供的四组hash值拼出hash id 可以看出,hash id会...

Python - Video to Ascii 影片转 Ascii 套件参考笔记

Python - Video to Ascii 影片转 Ascii 套件参考笔记 参考资料 Gith...