es6篇
推荐 CrazyCodeBoy的文章 ES6、ES7、ES8特性一锅炖(ES6、ES7、ES8学习指南)
1、ES6+你熟悉么,用过哪些特性?
- 箭头函数
- 类及引入导出和继承( class/import/export/extends)
- 字符串模板
Promiselet,constasync/await- 模块化
- 解构赋值
- 延展操作符
- 对象属性简写
2、let 和 const 有啥差异?
let会产生块级作用域,不会造成变量提升,无法重新声明(但可以重新赋值);const是常量,若是基本数据类型,具有不变性(无法重新赋值改动) 引用值可以调整内部值(可能设计的时候没有考虑周全!
3、async和await的用途?
让 promise 的异步变成同步运行成了可能,await 可以等到 promise 执行完毕
4、类、继承
class Animal {
// 构造函数,实例化的时候将会被调用,如果不指定,那么会有一个不带参数的默认构造函数.
constructor(name,color) {
this.name = name;
this.color = color;
}
// toString 是原型对象上的属性
toString() {
console.log('name:' + this.name + ',color:' + this.color);
}
}
var animal = new Animal('dog','white');//实例化Animal
animal.toString();
console.log(animal.hasOwnProperty('name')); //true
console.log(animal.hasOwnProperty('toString')); // false
console.log(animal.__proto__.hasOwnProperty('toString')); // true
class Cat extends Animal {
constructor(action) {
// 子类必须要在constructor中指定super 函数,否则在新建实例的时候会报错.
// 如果没有置顶consructor,默认带super函数的constructor将会被添加、
super('cat','white');
this.action = action;
}
toString() {
console.log(super.toString());
}
}
var cat = new Cat('catch')
cat.toString();
// 实例cat 是 Cat 和 Animal 的实例,和Es5完全一致。
console.log(cat instanceof Cat); // true
console.log(cat instanceof Animal); // true
5、模块化(Module)
模块的功能主要由 export 和 import 组成。
每一个模块都有自己单独的作用域,模块之间的相互调用关系是通过 export 来规定模块对外暴露的接口,通过import来引用其它模块提供的接口。同时还为模块创造了命名空间,防止函数的命名冲突。
- 导出(export)
ES6允许在一个模块中使用export来导出多个变量或函数。
1)导出变量
//test.js
export var name = 'Rainbow'
2)导出函数
// myModule.js
export function myModule(someArg) {
return someArg;
}
- 导入(import)
import {myModule} from 'myModule';// main.js
import {name,age} from 'test';// test.js
6、箭头函数this指向谁
箭头函数所改变的并非把 this 局部化,而是完全不把 this 绑定到里面去;
就是 this 是取自外部的上下级作用域(但是又不是常规 function的语法糖)..
因为箭头函数里并不支持var self = this 或者 .bind(this)这样的写法。
7、普通函数和箭头函数的区别
- this指向的问题,会捕获其所在上下文的 this 值,作为自己的 this 值。
- 箭头函数不绑定
arguments,取而代之用rest参数解决。
var foo = (...args) => {
return args[0]
}
console.log(foo(1))
- 箭头函数不能用作构造器,和
new一起用就会抛出错误。 - 箭头函数没有原型属性。
var foo = () => {};
console.log(foo.prototype) //undefined
8、静态方法,静态属性,私有变量么?
静态方法是ES6之后才有这么个玩意,有这么些特点
- 方法不能给 this引用,可以给类直接引用
- 静态不可以给实例调用,比如 let a = new ParentClass => a.sayHello() 会抛出异常
- 父类静态方法,子类
非static方法没法覆盖父类 - 静态方法可以给子类继承
- 静态属性可以继承也可以被修改
class ParentClass {
constructor(name) {
this.name = name;
}
static sayHello() {
console.log("I'm parent!" + this.name);
}
static testFunc(){
console.log('emm...Parent test static Func')
}
}
class SubClass extends ParentClass {
constructor(name) {
super(name);
}
sayChildHello() {
console.log("I'm child " + this.name)
}
static sayHello() {
console.log("override parent method !,I'm sayHello Method")
}
static testFunc2() {
console.log(super.testFunc() + 'fsdafasdf');
}
}
ParentClass.sayHello(); // success print
let a = new ParentClass('test');
a.sayHello() // throw error
SubClass.sayHello(); // 同名 static 可以继承且覆盖
SubClass.testFunc2(); // 可以继承
let testA = new SubClass('CRPER');
私有变量
WeakMap可以避免内存泄露,当没有被值引用的时候会自动给内存寄存器回收了.
const _ = new WeakMap(); // 实例化,value 必须为对象,有 delete,get,has,set四个方法,看名字都知道了
class TestWeakMap {
constructor(id, barcode) {
_.set(this, { id,barcode });
}
testFunc() {
let { id,barcode } = _.get(this); // 获取对应的值
return { id,barcode };
}
}
用Symbol来实现一个私有变量
9、谈谈你对 Promise 的理解? 和 ajax 有关系么?
Promise和ajax没有半毛钱直接关系.promise只是为了解决"回调地狱"而诞生的;
平时结合 ajax是为了更好的梳理和控制流程...这里我们简单梳理下..
es6 promise ajax
定义
const myHttpClient = url => {
return new Promise((resolve, reject) => {
let client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
function handler() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
}
});
};
使用
myHttpClient('https://www.baidu.com').then(res => {
console.log(res);
}).catch(error => {
console.log(error);
});
Promise有三种状态,Pending/resolve()/reject();
一些需要注意的小点,如下
- 在
Pending转为另外两种之一的状态时候,状态不可在改变.. Promise的then为异步.而(new Promise())构造函数内为同步Promise的catch不能捕获任意情况的错误(比如 then 里面的setTimout内手动抛出一个Error)Promise的then返回Promise.reject()会中断链式调用 -Promise的resolve若是传入值而非函数,会发生值穿透的现象Promise的catch还是then,return的都是一个新的Promise(在 Promise 没有被中断的情况下)
Promise 还有一些自带的方法,比如race,all,前者有任一一个解析完毕就返回,后者所有解析完毕返回...
10、实现一个 promise
首先你需要对 promise 有一个清晰的认识,封装过请求,使用过它的 api 等。
请参考 前端劝退师 的文章 「中高级前端面试」JavaScript手写代码无敌秘籍
11、实现一个按顺序加载的 promise
当你说出 promise.all 和 promise.race的区别后,面试官可能就会接着考察此题。
/* 使用 async await */
async function queue(tasks) {
const res = []
for (let promise of tasks) {
res.push(await promise(res));
}
return await res
}
queue([a, b, c])
.then(data => {
console.log(data)
})
12、实现一个 sleep 函数
//Promise
const sleep = time => {
return new Promise(resolve => setTimeout(resolve,time))
}
sleep(1000).then(()=>{
console.log(1)
})
//Generator
function* sleepGenerator(time) {
yield new Promise(function(resolve,reject){
setTimeout(resolve,time);
})
}
sleepGenerator(1000).next().value.then(()=>{console.log(1)})
//async
function sleep(time) {
return new Promise(resolve => setTimeout(resolve,time))
}
async function output() {
let out = await sleep(1000);
console.log(1);
return out;
}
output();
//ES5
function sleep(callback,time) {
if(typeof callback === 'function')
setTimeout(callback,time)
}
function output(){
console.log(1);
}
sleep(output,1000);
13、题目
Promise 必知必会(十道题): 有助于你更加深刻的了解 promise 的运行情况
更多的Promise 详情可以参考JavaScript Promise迷你书(中文版);