JS的底层小知识(二):预编译
前言
上篇文章简单的给各位讲了一下作用域,相信大家都有另一个清晰的认识,OK,那么我们继续往下走,一起来探索一下秘书是怎样工作的吧!
声明提升
在此之前,我们先简单的来了解一下什么是声明提升:
声明提升:在JS中,"声明提升"是指 变量和函数的声明 在代码执行前,会被提升到其所在作用域的最顶部。这并不意味着赋值操作也会被提升,只有声明部分会被提升。
变量声明提升
对于使用var
声明的变量,无论它们出现在代码的哪个位置,都会被提升到当前作用域的顶部。但是,变量的赋值操作不会被提升。
就比如以下代码:
console .log(a)
var a = 1
该段代码的输出结果为 undefined
,因为在代码执行前,var a 会被提升到全局作用域的顶部。
也就是这样:
var a
console .log(a)
a = 1
函数声明提升
函数声明也会被提升,但是函数是整体提升,也就是说函数会带着函数体内的东西一起被提升当前作用域的顶部。
就比如:
foo( )
function foo() {
var b = 1
console.log(b)
}
会变成:
function foo() {
var b = 1
console.log(b)
}
foo( )
注意:let
, const
和 函数表达式
使用let
和const
声明的变量以及函数表达式并不会被提升。为什么呢?
let
和const
声明的变量,严格遵循块级作用域的规则,不会提升,他们会在词法环境中,划出一块属于自己的词法作用域,声明在哪里,就在哪里。
关于什么是词法作用域,大家可以去我的上一篇文章中查找一下。
而函数表达式是什么呢?就好似这样的代码 var b=function(){}
,这种只会把变量b
的声明提升,不会带上赋予b
的函数function
所以它们在定义它们的代码执行之前是不可访问的。
预编译
什么是预编译呢?预编译就好比是一位秘书,而 JS 的编译器 V8 ,就是董事长。编译器(董事长)在执行代码前,肯定会有一位高效能干的秘书(预编译)。所以在你需要执行一段代码输出结果之前,预编译悄然启动,为编译器的执行做好充足的准备,以便编译器能正常顺利的执行并输出结果。
全局的预编译
首先,在你将输出指令发送给进程终端之后,秘书就会开始全局的预编译,下面有请看以下代码:
var gloabal = 100
function fn(a) {
console.log(a)
var a = 123
console.log(a)
function a() {}//函数声明
console.log(a)
var b=function(){}//函数表达式(变量声明)
console.log(b)
function d() {}
var d = a
console.log(d)
}
fn(gloabal)
秘书一看到这段代码,就会进行以下操作:
- 首先,创建一个全局的执行上下文对象(
GO
) - 其次,找变量声明,变量名作为
GO
的属性名,值为undefined
- 然后,找函数声明,函数名作为
GO
的属性名,值为 函数体function
- 最后,交给董事长(V8编译器)执行
董事长会一个个从上到下执行,先给gloabal
赋值为 100,然后执行fn(gloabal)
函数。此时就要执行fn()
函数,而编译总是在执行之前,所以就会开始函数的预编译。
函数中的预编译
好,秘书一看到这段函数体内的代码,就会进行一下操作:
- 首先,创建一个函数的 执行上下文对象 (
AO
) - 其次,找形参和变量声明,将形参和变量名作为
AO
的属性,值为undefined
- 再次,将实参和形参统一
- 然后,在函数体内找函数声明,将函数名作为
AO
的属性名,值赋予函数体 - 最后,交给董事长(V8编译器)执行
那么,秘书的小本本上是怎么记录的呢,也就是说,预编译的过程是什么呢?大家可以根据以上步骤先思考一下,并写出输出的结果,完事之后,来看看秘书的编译过程吧!
//全局的预编译
GO:{
gloabal:undefined
fn:function(){}
}
//全局的预编译结束,该到V8编译器执行
GO{
gloabal:undefined -> 100
fn:function -> 调用fn()函数
}
//函数的预编译
(第一步)
AO:{
第二步 第三步 第四步
a:undefined => 100 => function(){} => 123
b:undefined =>function(){}
d:undefined => function(){} => 123
}
//函数的预编译结束,该到V8编译器执行
AO:{
执行
a:undefined => 100 => function(){} => 123
b:undefined =>function(){}
d:undefined => function(){} => 123
}
所以输出结果为:
看看你的结果和我的一样吗?不一样的话,可以再看看,多思考,多动脑哦,也可以在评论区说出你的疑惑哦
写得不好的地方以及需要修改的地方,欢迎大佬亲临指正昂💞
转载自:https://juejin.cn/post/7373136303179431947