21校招滴滴前端一面

160 阅读5分钟

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的区别,以及那个性能较好

v8源码中都是通过for循环+回调方式实现的forEach、map,性能差不多。

3.讲讲html5的新特性

- 使用语义化标签的好处

- canvas

4.讲讲项目难点

5.webpack的运行原理

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

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

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

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

juejin.cn/post/685457…

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

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