JavaScript 关于面试题

请写出弹出值,并解释为什么。

~function () {
    alert(a);
    a();
    var a = function () {
        console.log(1);
    }

    function a() {
        console.log(2);
    }

    alert(a)
    a();
    var c = d = a;
}();

alert(d); 
alert(c); 
阅读 6k
11 个回答

实际上,这段代码是这么跑的:

~function () {
//hoisting
function a() {
    console.log(2);
}
var a;

alert(a);
a();
a = function () {
    console.log(1);
}

alert(a)
a();
d = a;
var c = d;
}();

alert(d); 
alert(c);

参考:hoisting

包括打印和alert的值如下:
1、

function a() {
   console.log(2);
}

2、2
3、

function a() {
   console.log(1);
}

4、1
5、

function a() {
   console.log(1);
}

原因: var c = d = a;从右向左执行,d=a,d没有使用var声明,是一个全局变量,方法外部可访问。
6、报错,原因:c是函数内部的变量,外部访问不到的,外部变量c是undefined。
其它的就不一一解释原因了,本质就是变量提升和函数声明提升的问题。

1: function a() {

console.log(2);

}

2,3 var a = function () {

console.log(1);

}

4: 报错
因为 函数提升优于变量提升 且 变量提升只声明不赋值, 局部变量作用于局部

你的代码最好用代码标记工具专门标记出来啊。

出这个问题的人是比较BT的。

试题与标题的this有关系么。其实本质就一点:函数提升优于变量提升,理解这个就好了。并且从这题也能看到函数定义的函数申明和函数表达式两种方式的差别。

词法分析:
0:函数的在运行的瞬间,生成一个活动对象(Active Object)就是所谓的AO

1:分析参数

  1-1:函数接收参数,添加到AO的属性上面,值全部都是undefine,如AO.age=undefine

  1-2:接收实参,形成AO对应的属性值

2:分析变量声明,如var age,

 2-1:如果AO上还没有age属性,则添加AO 属性,值是undefine

 2-2:如果AO 上面已经有了age属性,则不做任何操作。

3:分析函数的声明,例如funcion a(){},

3-1: 则把函数赋给AO.a,如果数据属性已经存在,则要被现在的新的值覆盖
4:执行 (赋值操作是执行中的过程);

放在这道题里就是:

分析参数:
即时函数没有参数;
分析变量:
函数内部 AO= {a:undifined,c:undefined} 全局 AO= {c:undefined}

分析函数的声明:
function a() {console.log(2);}
因为AO中已经存在a,a被覆盖为function a() {console.log(2);}
执行:
alert(a);//a就是函数声明 function a() {console.log(2);}
a();//执行a -->2
var a = function () {console.log(1);} a被赋值为新函数
function a() {console.log(2);} //已经分析过跳过
alert(a) // 弹出a 为新赋值的 function () {console.log(1);}
a(); 执行a 打印 1
var c = d = a; // c d 赋值为function () {console.log(1);}

即时函数执行完,向下执行

alert(d); //作用域中有d 为function () {console.log(1);}
alert(c); //作用域中没有c 报错c is not defined

关于这段代码,我关注两个问题:
1、alert 出什么?
2、对于

~function () {

    function code
    
    }();

这段语句为何能作为函数执行起来?
问题一的话,上面几位朋友说得很清楚,关于问题二就是通过 ~ ! || 等操作符使得解释器将函数声明能当做表达式来处理。
详见这里描述得很详细

主要考点就是函数和变量声明的提升顺序

~function () {

    alert(a) //function a(){ //coding }
    a();//console.log(2)

    var a = function () {
        console.log(1);
    }

    function a() {
        console.log(2);
    }

    alert(a)//a = function () { //coding }
    a();//console.log(1)
    var c = d = a;
}();
alert(d);//a = function () { //coding } d为全局变量
alert(c) //ReferenceError: c is not defined c是局部变量
~function (){
    function a() {
        console.log(2);
    }
    var a;
    var c;
    alert(a)
    a()
    a = function (){
        console.log(1)
    }
    alert(a)
    a();
    d = a
    c = d;
}()
console.log(d)
console.log(c)

个人感觉这样更加合理一点吧。

中间那段代码等同于如下

function a() {

console.log(2);

}
var a;

alert(a);
a();

a = function () {

console.log(1);

}

alert(a)
a();
var c = d = a;
首先了解变量提升和函数声明提升

function a() {

console.log(2);

}是函数声明,会提升到代码顶部
从上到下依次顺序:
1.弹出
function a() {

console.log(2);

}
2.后台打印出:
2
3:弹出
function () {

console.log(1);

}
4.后台打印出
1
5,6.都弹出
function () {

console.log(1);

}

这个问题其实是考你对JS预解析和闭包的理解,
function () {
alert(a); // 因为JS是单线程,而前面没有声明a所以这里报错
a(); //这里也会报错因为也没有声明
var a = function () { // 这里是一个函数表达式
console.log(1);
}
function a() { // 这里是声明一个函数
console.log(2)
}
alert(a) // 这里会打印一个函数,因为var声明的a被function声明的a函数层叠掉了
a(); // 这里当然是函数调用 打印2
var c = d = a; // 这里切记 并不是 var a , b ,c ; 所有d没有声明
}(); //这是一个闭包也是一个自调用函数
alert(d); //这里会报错
alert(c); // 这里会弹出一个函数体

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏