美文网首页前端开发那些事儿
记一次滴滴前端面试题以及补充相关前端复习

记一次滴滴前端面试题以及补充相关前端复习

作者: 汤川live | 来源:发表于2020-09-15 19:08 被阅读0次

    1.讲讲es6的新特性

    const,let,class,箭头函数,Promise,字符串模板

    - 块级作用域的es5实现

    使用立即执行函数函数作用域实现块级作用域

    (function(name){
      console.log('hello ' + name);// hello Bob
    })('Bob');
    

    - 类的继承方式es5和es6是怎样实现的?

    • es5继承
    
    function A() {
      this.a = 'hello';
    }
    
    function B() {
      A.call(this);
      this.b = 'world';
    }
    
    B.prototype = Object.create(A.prototype, {
      constructor: { value: B, writable: true, configurable: true }
    });
    
    let b = new B();
    

    代码中,构造函数 B 继承构造函数 A,首先让构造函数 B 的 prototype 对象中的proto 属性指向构造函数 A 的 prototype 对象,并且将构造函数 B 的 prototype 对象的 constructor 属性赋值为构造函数 B,让构造函数 B 的实例继承构造函数 A 的原型对象上的属性,然后在构造函数 B 内部的首行写上 A.call(this),让构造函数 B 的实例继承构造函数 A 的实例属性。在 ES5 中实现两个构造函数之间的继承,只需要做这两步即可。

    • es6继承
    class A {
      constructor() {
        this.a = 'hello';
      }
    }
    
    class B extends A {
      constructor() {
        super();
        this.b = 'world';
      }
    }
    
    let b = new B();
    

    代码中,类 B 通过 extends 关键字继承类 A 的属性及其原型对象上的属性,通过在类 B 的 constructor 函数中执行 super() 函数,让类 B 的实例继承类 A 的实例属性,super() 的作用类似构造函数 B 中的 A.call(this),但它们是有区别的,这是 ES6 与 ES5 继承的第二点区别,这个区别会在文章的最后说明。在 ES6 中,两个类之间的继承就是通过 extends 和 super 两个关键字实现的。

    • A.call(this)和super()的区别

    在 ES5 中,构造函数 B 的实例继承构造函数 A 的实例属性是通过 A.call(this) 来实现的,在 ES6 中,类 B 的实例继承类 A 的实例属性,是通过 super() 实现的。在不是继承原生构造函数的情况下,A.call(this) 与 super() 在功能上是没有区别的,用 babel 在线转换 将类的继承转换成 ES5 语法,babel 也是通过 A.call(this) 来模拟实现 super() 的。但是在继承原生构造函数的情况下,A.call(this) 与 super() 在功能上是有区别的,ES5 中 A.call(this) 中的 this 是构造函数 B 的实例,也就是在实现实例属性继承上,ES5 是先创造构造函数 B 的实例,然后在让这个实例通过 A.call(this) 实现实例属性继承,在 ES6 中,是先新建父类的实例对象this,然后再用子类的构造函数修饰 this,使得父类的所有行为都可以继承。

    - Promise的运行过程以及与async await的区别以及错误处理的方式

    Promise对象一开始的值是Pending准备状态。
    执行了resolve()后,该Promise对象的状态值变为onFulfilled状态。
    执行了reject()后,该Promise对象的状态值变为onRejected状态。
    Promise对象的状态值一旦确定(onFulfilled或onRejected),就不会再改变。

    Promise的异常捕获有两种方式:

    1. then中的reject方法捕获异常
      这种方法只能捕获前一个Promise对象中的异常,即调用then函数的Promise对象中出现的异常。
        var promise = Promise.resolve();
    
        promise.then(function() {
            throw new Error("BOOM!")
        }).then(function (success) {
            console.log(success);
        }, function (error) {
            // 捕捉的是第一个then返回的Promise对象的错误
            console.log(error);
        });
    

    复制代码但该种方法无法捕捉当前Promise对象的异常,如:

        var promise = Promise.resolve();
    
        promise.then(function() {
            return 'success';
        }).then(function (success) {
            console.log(success);
            throw new Error("Another BOOM!");
        }, function (error) {
            console.log(error);  // 无法捕捉当前then中抛出的异常
        });
    
    1. catch捕获异常
    var promise = Promise.resolve();
        promise.then(function() {
            return 'success';
        }).then(function (success) {
            console.log(success);
            throw new Error("Another BOOM!");
        }).catch(function (error) {
            console.log(error); // 可以正常捕捉到异常
        });
    

    总结来说就是:
    使用promise.then(onFulfilled, onRejected)的话,在 onFulfilled中发生异常的话,在onRejected中是捕获不到这个异常的。
    在promise.then(onFulfilled).catch(onRejected)的情况下then中产生的异常能在.catch中捕获
    .then和 .catch在本质上是没有区别的需要分场合使用。

    • async await错误处理
      一般情况下 async/await 在错误处理方面,主要使用 try/catch
    const fetchData = () => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('fetch data is me')
            }, 1000)
        })
    }
    
    (async () => {
        try {
            const data = await fetchData()
            console.log('data is ->', data)
        } catch(err) {
            console.log('err is ->', err)
        }
    })()
    
    
    (async () => {
        const fetchData = () => {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve('fetch data is me')
                }, 1000)
            })
        }
    
        const [err, data] = await fetchData().then(data => [null, data] ).catch(err => [err, null])
        console.log('err', err)
        console.log('data', data)
        // err null
        // data fetch data is me
    })()
    

    2.数组的遍历方式

    - map和forEach的区别,以及那个性能较好

    3.讲讲html5的新特性

    - 使用语义化标签的好处

    - canvas

    4.讲讲项目难点

    5.webpack的运行原理

    6.vue的特性,与其他框架的区别

    - 虚拟dom相比原生dom的优点和缺点

    1. 原生 DOM 操作 vs. 通过框架封装操作。
      这是一个性能 vs. 可维护性的取舍。框架的意义在于为你掩盖底层的 DOM 操作,让你用更声明式的方式来描述你的目的,从而让你的代码更容易维护。没有任何框架可以比纯手动的优化 DOM 操作更快,因为框架的 DOM 操作层需要应对任何上层 API 可能产生的操作,它的实现必须是普适的。针对任何一个 benchmark,我都可以写出比任何框架更快的手动优化,但是那有什么意义呢?在构建一个实际应用的时候,你难道为每一个地方都去做手动优化吗?出于可维护性的考虑,这显然不可能。框架给你的保证是,你在不需要手动优化的情况下,我依然可以给你提供过得去的性能。
      作者:尤雨溪
      链接:https://www.zhihu.com/question/31809713/answer/53544875
      来源:知乎
      著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    - vue-router的特性、运行原理

    https://juejin.im/post/6854573214485053453#heading-11

    vue router 是前端路由,当路径切换时,在浏览器端判断当前路径并加载当前路径对应的组件。

    • hash 模式:
      URL 中#后面的内容作为路径地址监听 hashchange 事件根据当前路由地址找到对应组件重新渲染
    • history 模式:
      通过 history.pushState() 方法改变地址栏监听 popstate 事件根据当前路由地址找到对应组件重新渲染

    相关文章

      网友评论

        本文标题:记一次滴滴前端面试题以及补充相关前端复习

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