美文网首页
一道让我蒙圈的 js 面试题

一道让我蒙圈的 js 面试题

作者: 溺水的鱼_fb44 | 来源:发表于2020-05-13 18:49 被阅读0次

    最近的面试题几乎都在考 XX 的原理,XX 的源码,XX 的算法,手写代码。原来不懂,只要会用不就行了吗?为什么要考原理、考源码?

    这是我原来不太明白的一个问题,后来才发现,懂得源码,懂得原理,写代码就会有一种行云流水般的的流畅感,代码看着也会优雅舒适。

    想要做到这一步,需要日积月累。今天也累积一点点。

    这个面试题主要是考察变量提升,运算符的优先级。原题是输出的 this,而不是数字,先看简单一点的,题目如下:

    function Foo() {
        x = function () {
            console.log(1);
        };
        return this;
    }
    
    Foo.x = function () {
        console.log(2);
    };
    
    Foo.prototype.x = function () {
        console.log(3);
    };
    
    var x = function () {
        console.log(4);
    };
    
    function x() {
        console.log(5);
    }
    
    //请写出以下输出结果:
    
    Foo.x();
    x();
    Foo().x(); 
    x();
    new Foo.x(); 
    new Foo().x();  
    new new Foo().x(); 
    

    看这个题之前我们先看一下涉及到的一些知识点。

    变量提升

    使用 var 声明变量会有变量提升的问题,function 也会提升,看个例子:

    // 第一处 a();
    var a = function () {
         console.log(1);
    };
    // 第二处 a();
    function a() {
        console.log(2);
    }
    // 第三处 a();
    

    上面的代码,在三处调用时,第一处结果是 2,第二和第三处是1
    引擎在处理时,会编译成下面这样:

    var a;
    function a() {
        console.log(2);
    }
    // 第一处 a();
    a = function () {
        console.log(1);
    }
    // 第二处 a();
    // 第三处 a();
    

    变量的声明会被提升,但是赋值还是在定义的地方处理。函数也会声明,包括函数体,所以会出现上面的结果。

    运算符优先级

    可以看 MDN 关于 运算符优先级的说明。下图是这里会涉及到的运算符的优先级排列。

    运算符优先级.png

    看了上面的知识,我们现在看一下上面的题目。

    Foo.x();

    这个很简单,就是访问函数上定义的变量。结果为 2
    这里的 . 是成员访问,() 是函数调用,都是从左到右执行。

    x();

    这个就考到了变量提升。
    我们看到有三个地方可以产生全局变量 x。但是在 Foo函数内定义的,还没有执行,所以这里只有 var xfunction x。最后的结果就是 4var x 覆盖了 function x

    Foo().x();

    函数调用和成员访问,是同一级别的优先级,从左到右依次执行。Foo() 执行,生成全局变量 x,这个会覆盖原来的 x,所以结果是 1

    x();

    这个在上一步的时候已经说了,现在是函数 Foo中定义的 x,结果是 1

    new Foo.x();

    这个 new ... 是无参数列表,优先级比成员访问要低。先执行成员访问,可以看成这样 new (Foo.x)(),然后形成了 new 带参数列表,这个是个整体,执行结果就是 2

    new Foo().x();

    这个有个 new 带参数列表,有个成员访问,有个函数调用,他们是同一级别,执行顺序从左到右,可以写成这样 (new Foo()).x() 最后是调用 Foo 实例上的 x,最后的结果是就是 3。

    new new Foo().x();

    这个 有 new 带参数列表,new 无参数列表,成员访问 函数调用。new 无参数列表优先级最低,可以写成这样new (new Foo()).x(); 。然后它的执行顺序就可 new Foo.x() 原理一样了,不过这里的是实例上的 x,所以最后的结果是 3。

    这个是比较简单的实例,如果把打印的日志换成 this,结果又是什么呢?有兴趣可以试一下,自己写出答案,然后运行一下代码,看看和自己想的是否一致。

    参考:前端同学经常忽视的一个JavaScript面试题
    《你不知道的 JavaScript (上卷)》

    相关文章

      网友评论

          本文标题:一道让我蒙圈的 js 面试题

          本文链接:https://www.haomeiwen.com/subject/agnmnhtx.html