题目一
{
console.log("gb:" + i);
var i = 1;
foo(1);
function foo(i) {
if (i == 4) {
return;
}
console.log("fb:" + i);
foo(i + 1);
console.log("fe:"+i);
}
console.log("ge:"+i);
}
答案:
首先第一句打印:因为var声明的变量存在变量提升,所以i是undefined。
然后就是调用foo函数。
首先先了解函数调用栈:
函数的执行会有一个函数调用栈来存储函数相关的数据,当调用一个函数就会把该函数进行入栈,只有函数体内的代码执行完成后才会出栈。
现在回到题目:
foo(1);
function foo(i) {
if (i == 4) {
return;
}
console.log("fb:" + i);
foo(i + 1);
console.log("fe:"+i);
}
第一次调用函数foo(1),函数会先打印"fb:1",然后遇到foo(i+1);就再一次执行foo(2),但是foo(1)还有最后一句(console.log(“fe:”+i))没有执行完成。所以foo(1)还没有出栈,而是又入栈了foo(2)。
看图解:
foo(1)、foo(2)、foo(3)都进不去if语句,不能结束函数,所以就会依次入栈,且foo(1)、foo(2)、foo(3)的最后一行都没执行,当遇到foo(4)的时候,进去if语句return,这时候return结束的是foo(4),所以foo(4)出栈,下一步就再执行foo(3)剩下的最后一行代码:console.log(“fe:”+3),foo(3)执行完出栈再执行foo(2)剩下的代码,foo(2)执行完出栈再执行foo(1),foo(1)执行完,然后所有的代码执行完成,栈空。
输出结果:
题目二:
function a() { };
var a;
console.log(typeof a);//输出 "function"
这里就是函数提升和变量提升的优先级,
JS首先会进行编译阶段:就是先进行对函数的提升,然后再对变量的提升,这里的执行过程应该是这样:首先进行函数提升,a保存的就是函数a的地址,然后再进行var进行声明但是不进行赋值,它会去找window比它先进行提升的是否存在,如果有,就保存最初的值,没有在进行undefined,如果是赋值的话,那么就会报保存之后的值。
看代码:
{
var a = 3;
var a;
console.log(a); //输出3
}
{
var a = "";
var a;
console.log(a) //输出 “”
}
代码表示:
function a(){};
var a
console.log(typeof a);
//如果是:这样
function a(){};
var a = 2
console.log(typeof a)//number;
相当于:
function a(){};
var a;
a = 2
console.log(typeof a)//number;
题目三
if (!(a in window)) {
var a = 10;
}
console.log(a);//输出 undefined
首先有个用var声明的a,a就在window下存在,但是它的值现在还是undefined,所以a in window是true,这时候进不去if语句,所以a输出是undefined。