千金一刻莫空度,老大无成空自伤。这篇文章主要讲述JavaScript之预编译学习(内含多个面试题) #yyds干货盘点#相关的知识,希望能为你提供帮助。
前言在学习javascript
预编译之前,先了解一下javaScript
从编译到执行的过程,大致可分为四步:
- 词法分析
- 语法分析:检查代码是否存在错误,若有错误,引擎会抛出语法错误。同时会构建一颗抽象语法树(
AST
)。 - 预编译
- 解释执行
js
中预编译一般有两种:全局的预编译和函数的预编译,分别发生在script
内代码执行前和函数的执行前。函数预编译首先来看一个例子:
function test(a)
console.log(a);
var a = 123;
console.log(a);
function a()
console.log(a);
var b = function()
console.log(b);
function d() test(1)
就以上述例子中的
a
为例,有形参a
,变量a
,函数a
,那test
函数执行时,此时的a
到底是什么呢?输出结果:
? a()
123
123
? ()
要想弄明白最终的输出结果,就不得不好好学习一下预编译的详细过程。
在预编译学习中,经常听到一句话:函数声明整体提升,变量声明提升。
这句话可以解决大多数场景下的预编译面试题,但光凭这句话无法吃透预编译的,因此接下来我们来一起捋一下函数预编译的详细流程。
函数预编译四部曲
- 预编译开始,会建立
AO(Activation Object)
对象 - 找形参和变量声明,使其作为
AO
的属性名,值赋予undefined
- 实参和形参相统一(将实参值赋值给形参)
- 找函数声明,函数名作为
AO
属性名,值赋予函数体 案例分析
学习了函数的预编译过程,就可以回头细细的品味一下上面的案例:
- 先建立
AO
,并找形参和变量声明,值赋予undefined
AO : a: undefined, b: undefined
- 形参实参相统一
AO : a: 1, b: undefined
- 找函数声明,值赋予函数体
AO : a: function a() , b: undefined, d: function d()
- 预编译过程结束,挨着分析一下
console
的打印结果:第一个console.log(a); // 此时AO中a的值为function a() 执行赋值操作: a = 123 // AO中的a值修改为123 第二个console.log(a) // 123 第三个console.log(a) // 123 b = function()// AO中的b值修改为function b() console.log(b) // function b()
全局预编译三部曲
- 生成
GO(Global Object)
- 找变量声明,由于全局变量默认挂载在
window
之上,若window
当前已存在当前属性,忽略当前操作,若没有,变量作为属性名,值赋予undefined
。 - 找函数声明,函数与变量类似,先去
window
上查看,不存在,函数作为函数名,值为函数体 案例分析
将函数预编译案例稍微修改,如下:
// test部分的结果与函数部分相同,再次只分析全局部分
console.log(a);
var a = 1;
console.log(a);
function test(a)
console.log(a);
var a = 123;
console.log(a);
function a()
console.log(a);
console.log(b);
var b = function()
console.log(b);
test(2);
- 生成
GO
,变量提升,函数提升,得到GO
如下:GO/window: a: undefined, test: function()
- 因此第一个
a
的值为undefined
,随后a
赋值为1
,所以第二个a
的值为1
【JavaScript之预编译学习(内含多个面试题) #yyds干货盘点#】2. let/const声明的变量应当同样进行了变量提升,只不过它与var声明的变量做了一定的区分
常见面试题分析 题目一
function test()
console.log(b);
if (a)
var b = 100;
console.log(b);
c = 234;
console.log(c);
var a;
test();
a = 10;
console.log(c);
- 生成
GO
GO: a: undefined, test: function test() , c: undefined
test
执行,生成test
的AO
// AO还会存储[[scope]]属性,存储AO的作用域链AO: b: undefined, [[scope]]: [TestAO, GO]
- 分析
test
函数执行console.log(b) // AO中b为undefined if (a) // AO中无a,沿[[scope]]找到GO中的a,值为undefined b = 100; // 不执行 console.log(b) // undefined c = 234; // AO中没有c属性,沿[[scope]]找到GO中的c修改为234 console.log(c) // 打印的是GO中的c,234 // test执行完毕,AO销毁
- 分析剩余代码:
a = 10; // GO中的a修改为10 console.log(c) // GO中c值为234,234
var foo = 1;
function bar()
console.log(foo);
if (!foo)
var foo = 10;
console.log(foo);
bar();
答案
undefined
10
题目三
var a = 1;
function b()
console.log(a);
a = 10;
return;
function a()b();
console.log(a);
return; 与上面案例的if一样,预编译环节不会处理
答案
function a()
1
题目四
console.log(foo);
var foo = "A";
console.log(foo)
var foo = function ()
console.log("B");
console.log(foo);
foo();
function foo()
console.log("C");
console.log(foo)
foo();
答案
? foo()
console.log("C");
A
? ()
console.log("B");
B
? ()
console.log("B");
B
题目五
var foo = 1;
function bar(a)
var a1 = a;
var a = foo;
function a()
console.log(a);
a1();
bar(3);
答案
1
总结预编译的题目多数情况下就可以采用以下原则:
- 函数声明,整体提升
- 变量声明,声明提升
最后,在预编译时一定要注意:
return、if
等代码逻辑判断是在执行时候做的,预编译不管这些,预编译只管变量、形参、函数等。推荐阅读
- SangFor授权上架网络配置(AC12.0.46)
- 使用VM虚拟机安装CentOS-stream系统
- 带你了解HTML基本标签的使用#yyds干货盘点#
- 微软与维珍航空圣诞节福利狂送Windows 8平板
- Win8系统下打开磁盘管理器的3种办法【图文】
- 找到win8旗舰版64位系统失去的桌面磁贴【图文】
- Win8内部版系统Build 8331现身Windows应用商店处于失效状态
- 迪拜将为450万WP8.1用户提供运营商代收费技巧
- 开发者评论微软WP8.1/Windows 8通用应用目前的开发现状