这套题还不错,感兴趣的猿可以试一试:前端开发工程师
JS运行代码通常分为三步
1.语法分析
2.预编译
3.解释执行
那么什么叫做预编译呢?
即代码被执行前需要做的准备就称为执行上下文或者预编译
我们先来看一段代码
var a = 1
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(1)
试问这段代码的五个console.log();执行出来的结果会是多少呢?让我们大家一起来看一看
ƒ a() {}
123
123
ƒ (){}
123
这个时候就会有人问了,短短的几行代码,怎么执行出来的结果如此不同?
此时,预编译就要隆重登场了!!!
!!!预编译 -发生在函数(函数体内)执行之前 四部曲
1.创建一个AO对象 (activation object)
2.找形参和变量声明,将形参和变量声明作为AO对象的属性名,值为underfined
3.将实参和形参统一
4.在函数体里找函数声明,将函数名作为AO对象的属性名,值赋予函数体
就以上面那个例子来对这个四部曲进行说明:
第一,创建一个AO对象
AO{
}
第二,找形参和变量声明,将形参和变量声明作为AO对象的属性名,值为underfined
AO{
a:underfined,
b:underfined,
d:underfined
}
第三,将实参和形参统一
AO{
a:underfined 1,
b:underfined,
d:underfined
}
第四,在函数体里找函数声明,将函数名作为AO对象的属性名,值赋予函数体
AO{
a:underfined 1 function a() {},
b:underfined,
d:underfined function d(){}
}
最后,按照预编译的这四步去执行便会得到前文的执行结果。
这个时候又要注意了,预编译不仅发生在函数体内,同时也发生在全局作用域下面。
同样一段代码奉上
global = 100
function fn() {
console.log(global);
global = 200
console.log(global);
var global = 300
}
fn()
让我们看看这里的值又会是多少呢?
undefined
200
!!!预编译 - 发生在全局作用域下面 三部曲
1.创建一个GO对象
2.找变量声明,将变量声明作为GO对象的属性名,值赋予underfined
3.找全局里的函数声明,将函数名作为GO对象的属性名,值赋予函数体
这里也是一样的,用上面的例子(第二段代码)对这三部曲进行说明:
第一,创建一个GO对象
GO{
}
第二,找变量声明,将变量声明作为GO对象的属性名,值赋予underfined
由于函数体在函数内,所以函数体也要进行预编译
AO{
global:underfined
}
第三,找全局里的函数声明,将函数名作为GO对象的属性名,值赋予函数体
全局下的预编译
GO{
fn:function(){}
}
执行如下:
AO{
global:underfined
}
GO{
fn:function(){}
global:100 //全局下找不到global变量新建的
}
总结
预编译到这里就告一段落了,如果以后碰上预编译的问题就可以用这个预编译三部曲和四部曲进行解决啦。如有其他的见解可评论区留言哦,在学前端小白一枚,还望大家多多指教!