今天在看面试题的时候发现自己很多东西不了解,比如函数预编译,好多题目的答案与这个函数预编译有着极大的关联。然后我就大致总结了一下预编译的顺序。以及预编译的概念。
记住在面试题中,首先将形参和声名的变量提升,设置为undefind,然后将形参赋值,在接下来就是最后一步给对应的函数名赋值函数。预编译阶段完成后,就开始执行,遇到赋值的情况直接覆盖即可。
首先说一下为什么预编译!
JS属于解释型语言,在执行过程中顺序执行,但是会分块先预编译然后才执行。因此在JS中存在一种变量提升的现象。搞懂预编译环节,变量提升自然而然也就懂了。
然后说一下预编译的具体顺序!
1 创建AO对象,执行期上下文(后面更新关于执行期上下文详解)。
2 寻找函数的形参和变量声明,将变量和形参名作为AO对象的属性名,值设定为undefined.
3 将形参和实参相统一,即更改形参后的undefined为具体的形参值。
4 寻找函数中的函数声明,将函数名作为AO属性名,值为函数体。
只要照着这个顺序去思考问题,基本上能够解决大多数函数问题。我在底下附上我拷贝别人博客的例题。
function fn(a) {
console.log(a);
var a = 123;
console.log(a);
function a() {}; //输出结果是: ƒ a() {} 123 123 ƒ () {}
console.log(a);
var b = function() {};
console.log(b);
function d() {};
}
//调用函数
fn(1);
function test(a, b) {
console.log(a);
c = 0;
var c;
a = 3;
b = 2;
console.log(b);
function b() {};
function d() {};
console.log(b); //输出结果是1 2 2
}
//调用函数
test(1);
console.log(test);
function test(test) {
console.log(test);
var test = 234;
console.log(test);
function test() {};
}
test(1);
var test = 123;
输出结果是这样的
ƒ test(test) {
console.log(test);
var test = 234;
console.log(test);
function test() {};
}
ƒ test() {}
234
var a = 1;
function f(){
console.log(a);
if(false){
var a= 2;
}
}
f();
输出:undefined,因为函数预编译阶段var a=2;声明提前,如果要设置为1将var改为let即可。