前言:22届菜鸡前端正在实习中,总感觉基础不牢固,正在补 JavaScript 基础,随笔记录所学、所想。
一、函数体中的预编译过程
在函数体中搞懂javascript的预编译流程,下面先看代码,打印出执行顺序:
function test(a) {
console.log(a);
var a = 1;
console.log(a);
function a() {}
console.log(a);
var b = function () {};
console.log(b);
function c() {}
console.log(c);
}
test(1);
先说答案,依次执行顺序为:
function a() { }
1
1
function () { }
function c() { }
为什么?下面解释一下预编译的流程,函数体中只需要4步即可搞懂:
- 找形参和变量声明
- 找实参
- 找函数声明
- 依次执行
当页面初次加载时,首先会执行
test(1)
函数,然后执行内部操作。
第一步:找每个形式参数:
- 函数体中形参为
a
,这时形参a
是undefined
所以a = undefined
。 - 函数体中变量有
a
和b
,变量提升后a = undefined
,b = undefined
。 第二步:找实参: - 函数传递的实参为
1
,这时a = 1
。 第三步:找函数声明: - 当前
test
函数中存在函数体function a() { }
,function c() { }
,函数内部提升函数体,此时a = function a() { }
,c = function c() { }
。 第四步:自顶向下依次执行: - 首先执行
console.log(a)
打印出function a() { }
,然后1
赋值给变量a
,此时a = 1
; - 再次执行
console.log(a)
,此时打印出1
,再执行console.log(a)
不变,继续打印出1
,然后function () { }
赋值给变量b
,此时变量b = function () { }
; - 再次执行
console.log(b)
,打印出function () { }
; - 最后执行
console.log(c)
,打印出function c() { }
。
二、全局预编译过程
作用于全局作用域中的预编译过程,下面看代码,打印出执行顺序:
var b = 1;
console.log(a);
function a(a) {
console.log(a);
var a = 2;
console.log(a);
function a() {}
var b = 5;
console.log(b);
}
a(1);
先说答案,依次执行顺序为:
function a(a){ // ...函数内 }
function a() { }
2
5
下面详细说一下全局的预编译流程,全局作用域中,只需要3步即可搞懂:
- 找函数声明
- 找变量声明
- 依次执行
第一步:找函数声明
- 找到函数
function a(a){ // ...函数内 }
,函数提升后此时a = function a(a){ // ...函数内 }
; 第二步:找变量声明: - 找到变量
b
,变量提升后此时的b = undefined
; 第三步:自顶向下依次执行: - 首先将
1
赋值给变量b
,此时b = 1
,执行console.log(a)
,打印出a = function a(a){ // ...函数内 }
,再次执行函数a
,函数体中使用上面的四步操作; - 找形参和变量声明:找到形参
a
,此时a = undefined
,然后变量a
,b
提升,此时a = undefined
,b = undefined
; - 找实参:执行
a(1)
时,传递实参1
,此时a = 1
; - 找函数体:找到函数
function a() { }
,此时a = function a() { }
; - 依次执行:执行
console.log(a)
,打印出function a() { }
,然后将2
赋值给变量a
,此时a = 2
,再次执行console.log(a)
,打印出2
,再次执行将5
赋值给变量b
,此时b = 5
,执行到console.log(b)
时,打印出5
。
以上就是 JavaScript 中预编译的执行过程,虽然很基础,但是日常开发中用处非常大,建议多看几遍,有些许绕圈的感觉~ 注意:以下为同一个作用域内
- 对于同名的变量,
JavaScrip
会优先采用先声明的变量,后声明的同名变量会被忽略,变量默认为undefined
。 - 对于同名的函数,
JavaScrip
会采用最后声明的函数,之前声明的同名函数会被覆盖,因为函数声明会指定函数内容,所以保留的是最后一次的声明。 - 对于同名的变量和函数,
JavaScrip
是函数优先提升,所以同名的变量一定不会被提升,后声明的同名变量会直接被忽略。
三、关于
- 实习一年半的前端练习生。
- 2022届毕业。
- 目前公司技术栈 React + TypeScript + Egg。
- 啥都做呀,还就那个全干!
- 目前处于啥都会点,啥也都不会。