「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」
一、题目描述
以下代码输出顺序
var a = 1;
console.log(a);
function fn(a, c){
console.log(a);
var a = 123;
console.log(a);
console.log(c);
function a(){};
if(false) {
var d = 999;
}
console.log(d);
console.log(b);
var b = function(){};
console.log(b);
function c(){};
console.log(c)
}
var c = function (){
console.log("I at C function");
}
console.log(c);
fn(1, 2);
二、分析
- 页面产生便创建了GO全局对象(Global Object)
- 第一个脚本文件加载
- 脚本加载完毕后,分析语法是否合法.
- 开始预编译,查找变量声明,作为GO属性,值赋予undefined; 查找函数声明,作为GO属性,值赋予函数体;
//抽象描述
GO/window = {
a: undefined,
c: undefined,
fun: function(a, c) {
...
}
}
解释执行代码(直到执行调用函数fn(1, 2)语句)后,每个属性都赋了值
//抽象描述
GO/window = {
a: 1,
c: function (){
console.log("I at C function");
}
fn: function(a) {
...
}
}
所以在fn执行前打印出了
1
function c() {}
执行fn前也发生了一次函数预编译,创建了AO活动对象(Active Object)
// 首先查找形参和变量声明,并赋值 undefined
AO = {
a: undefined,
c: undefined,
d: undefined,
b: undefined
}
// 把实参赋值给形参
AO = {
a: 1,
c: 2,
d: undefined,
b: undefined
}
// 接下来查找函数声明,会覆盖变量声明
AO = {
a: function a() {},
c: function c() {},
d: undefined,
b: undefined
}
然后开始解释执行:
- 第一个console.log(a),毫无疑问会打印出我们上面分析的值
function a() {} - 第二个console.log(a),因为前面对变量a赋值了123,所以打印出
123 - 第三个console.log(c),打印出
function c() {} - 第四个console.log(d),因为条件语句的条件是false,所以不会进行赋值,打印出
undefined - 第五个console.log(b),打印出
undefined - 第六个console.log(b),前面一句为变量b赋值了一个函数,所以打印出
function() {} - 第七个console.log(c),打印出
function c() {}
综上所述,我们就可以知道
// 全局环境内首先打印出了
1
function c() {}
// 执行 fn 函数后打印出
function a(){}
123
function c(){}
undefined
undefined
function (){}
function c(){}
三、总结
分析预编译时,只要按照下面的步骤进行分析,我们就能够找出正确的答案了
- 创建AO对象
- 先找形参和变量声明,再找函数声明
- 形参和实参相统一
- 查找函数声明,会覆盖变量声明