前言:

想零碎学习前端面试题,强烈推荐浏览 在线电子书(反对手机版,不断更新) 。

本书特点:零碎全面(涵盖前端核心技术点),简洁,针对性强(针对面试场景设计)。

欢送在github上留言反馈

ES6+

[TOC]

介绍下Generator?

Generator函数是ES6提供的一种 异步编程解决方案,Generator函数是分段执行的,yield表达式是暂停执行的标记,而next办法能够复原执行

Generator函数是一个状态机,封装了多个外部状态。执行Generator 函数会返回一个遍历器对象,能够顺次遍历Generator函数外部的每个状态。

Generator与一般函数的区别:

  • 【不执行】调用Generator函数后,该函数并不执行
  • 【返回指针】返回的是一个指向外部状态的指针对象,而不是函数运行后果(遍历器对象 Iterator Object)
  • 【持续运行】必须调用遍历器对象的next办法,使得指针移向下一个状态,每次调用next办法,就继续执行,直到遇到下一个yield表白 式(或return语句)为止。

Generator API:

  • next(): 返回一个由yield 表达式生成的值
  • return(): 返回给定的值并完结生成器
  • throw(): 向生成器抛出一个谬误
function* helloWorldGenerator(){    yield 'hello';   //遇到yield 暂停执行    yield 'world';    return 'ending';}let hw = helloWorldGenerator();  //调用不执行函数,只是返回一个遍历器对象hw.next();  //{value:'hello',done:false}  调用next办法继续执行,直到遇到yield或return表达式hw.next(); //{value:'world',done:false}hw.next(); //{value:'ending',done:true}hw.next(); //{value:undefind,donw:true}  

参考资料:

Generator 函数的语法

ES6 Set 和 Array 的区别?

区别:

  • 【重复性】

    • set: value不反复 //通过此个性,可用来去重
    • array: value 可反复

ES6 Map和Objects的区别?

Map对象保留键值对,工作值(对象或原始值)都能够做为一个键或一个值

区别(Maps的长处):

  • 【key值类型】

    • Map:key能够是对象
    • Objects: key只能是一个string 或是 symbol
  • 【键的程序】

    • Map: 有序
    • Objects: 无序
  • 【size】

    • -Map: 减少size属性,间接获取
    • Objects: 只能依附手动计算
  • 【键名抵触】

    • Map: 默认不蕴含任何键,只蕴含显式插入的键
    • Object: object都有本人的原型,原型链上的键名有可能和你本人对象上的设置的键名产生抵触 (ES5开始可用Object.create(null)来创立一个没原原型的对象,但这种用法不常见)
  • 【性能】

    • Map: 在频繁增删键值对的场景下体现更好
    • Object: 在频繁增加/删除键值对的场景下未作出优化

箭头函数的this 指向哪里?

  • 默认绑定外层this
  • 不能应用call办法批改外面的this

    • -起因:函数的this能够用call办法来手动指定,而为了缩小this的复杂性,箭头函数无奈用call办法来指定this

参考资料:

JS中的箭头函数与this

箭头函数与一般函数区别?

箭头函数的长处

  • 语法更简洁

    • 不必写function 更简洁 // let sum=()=>{console.log(11);}
    • 只有一个参数的状况下,不必括号,间接写参数 // let sum = num1= > num1*2
    • 返回体只有一句的状况下,能够省去大括号 // let sum=(num1,num2)=> num1+num2
    • 如果箭头函数的函数体只有一条语句,并且 须要返回值,能够给这条语句前加一个 void // let fn=()=> void donotReturn()
  • 箭头函数不会创立本人的this (它只会从本人的作用域上一层继承this)

    • 定义时所处外层如执行环境的上下文,并继承这个 this,之后永远不会批改
var id = 'Global';function fun1() {    // setTimeout中应用一般函数    setTimeout(function(){        console.log(this.id);    }, 2000);}function fun2() {    // setTimeout中应用箭头函数    setTimeout(() => {        console.log(this.id);    }, 2000)}fun1.call({id: 'Obj'});     // 'Global'fun2.call({id: 'Obj'});     // 'Obj'

参考资料:

ES6 - 箭头函数、箭头函数与一般函数的区别

什么是严格模式(use strict)?

特点:

  • 【谨严】对语法要求更标准,打消js语法的一些不合理、不谨严之处,缩小一些怪异行为
  • 【平安】打消代码运行的一些不平安之处
  • 【高效】进步编译器效率,减少运行速度
  • 【扩展性】为将来新版本js做好铺垫

调用形式:在代码最后面增加一行代码("use strice";)

  • 针对整个脚本文件
  • 针对单个函数

扭转:

  • 全局变量显式申明:不能省略 var/const/let 关键词
  • 动态绑定:让属性和办法在编译阶段就确定指向哪个对象

    • 禁止应用with语句
    • 创设eval作用域
  • 加强字全措施:

    • 禁止this 指向全局对象
    • 禁止在函数外部遍历调用栈
  • 禁止删除变量(除非configurable 属性为true)
  • 显式报错:

    • 只读属性赋值
    • 对禁止扩大的对象增加新属性:
    • 删除一个不可删除的属性: delete object.prototype
  • 重名谬误
  • 对象不能重名的属性(之前是笼罩)
  • 函数不能有重名的参数
  • 禁止八进制表示法
  • arguments对象的限度:arguments是函数的参数,对它的应用做了限度

    • 不容许对arguments赋值
    • arguments 不再追踪参数的变动
    • 禁止应用arguments.callee: 无奈在匿名函数外部调用本身
  • 函数必须申明在顶层:不容许在非函数的代码块内申明函数(比方if,for),只容许在全局作用域或函数作用域的顶层申明函数
  • 保留字:新增了一些保留字,向未来js新版本过渡

    • let ,private,public,static ,package,yield,interface,protected,implements

js语法不标准的几个中央:

  • 【变量定义】能够不应用 var/const/let 关键词,间接定义

参考资料:

Javascript 严格模式详解

介绍下js的装璜器(decorators)?

Decorator 就是一种动静地往一个类中增加新的行为的设计模式,它能够在类时,扩大一个类的性能,并且 去批改类自身的属性和办法,使其能够在不同类之间更灵便的共用一些属性和办法;

润饰模式(Decortaor),是面向对象编程畛域中,一种动静地往一个类中增加新的行为的设计模式。润饰模式相比生成子类更加灵便,这样能够给某个对象而不是整个类增加一些性能

用法:

1) 装璜类

@FooDecoratorclass Foo {}function FooDecorator(target){    // target 就是这个 class 的原型对象}

2) 装璜属性

//给MyClass 所有实例的  getType 属性设置为仅为可读不可更改的属性 readonlyclass MyClass {    constructor(){        this.type="myClass"    }    @readonly    getType(){        return this.type    }}function readonly(target, key, discriptor){    discriptor.writable = false    return discriptor}

3)多个装璜器

class MyClass {    constructor(){        this.type="myClass"    }    @readonly    @logHello    getType(){        return this.type    }}//装璜器让类的getType办法不可更改function readonly(target, key, discriptor){    discriptor.writable = false    return discriptor}//让每次调用类中的getType办法会在控制台输入 hellofunction logHello(target, key, discriptor){    const oldFn = target[key]    target[key] = function(...rest){        console.log('Hello')        return oldFn.call(this,...rest)    }    return target}

参考资料:

JS 装璜器,一篇就够
[学习 ES7 语法 decorator 装璜器]()

创建对象的三种形式?

  • 字面量
  • 构造函数
  • Object.create

参考资料:

[Object.create()、new Object()和{}的区别]()

箭头函数?

ES6罕用 API有哪些?

let,const: 变量,常量
变量的解构赋值:
promise:解决异步
字符串扩大: for..of字符串遍历接口,repeat将一个新字符串分量N次,模板字符串$(baseUrl)
数值扩大:math.trunc()去掉小数局部,sign判断一个数是正/负/零,指数运算符**,
函数扩大:箭头函数(不绑定本人的this)
数组扩大:填充数组(fill),复制数据const a2=[...a1]
对象扩大:
正则的扩大:
减少async函数: 对异步的解决

AMD和CMD的区别,ES6模块与CommonJs 模块有什么区别?

罕用的模块化办法:

模块名导出模块引入模块加载形式阐明
ES6exportimport动态加载输入的援用,动态援用,只读属性
commonjsmodule.exportsrequire动静援用输入值的浅拷贝对象,动静加载,可读可写。nodejs中的规范
AMD(requirejs)definerequire异步依赖前置,提前执行(在模块定义的时候就要引入)
CMD(sea.js)definerequire(["jquery","math"],,()=>{})异步依赖就近,提早执行(用到的时候才引入)

CommonJs(require) 与 ES6(import)的区别:

  • require: 输入的是一个值的浅拷贝对象,import输入的是一个值 的援用(即es6 module 只存只读,不能扭转其值,具体点就是指针指向不能变,相似const)
  • require是动静引入,import是动态加载了;动静引入的形式,引入的对象能够是一个变量,或者能通过计算出来的地址
  • require是同步加载模块,import命令是异步加载,require有一个独立的模块依赖的解析阶段

参考: https://es6.ruanyifeng.com/#d...

/ AMD写法 /

define(["a", "b", "c", "d", "e", "f"], function(a, b, c, d, e, f) {     // 等于在最后面申明并初始化了要用到的所有模块    a.doSomething();    if (false) {        // 即使没用到某个模块 b,但 b 还是提前执行了        b.doSomething()    }});

/ CMD写法 /

define(function(require, exports, module) {    var a = require('./a'); //在须要时申明    a.doSomething();    if (false) {        var b = require('./b');        b.doSomething();    }});

js中let ,var 区别,let有什么长处?

相同点:都是定义这是的,都能够批改

let 长处:

  • 不能反复申明:var能够反复申明
  • 不存在变量晋升:let 不存在变量晋升,未定义的变量会报 : 未捕捉的援用谬误
  • 暂时性死区: 只有块级作用域内存在let命令,它所申明的变量变绑定这个区域,不再受内部影响
  • 领有块级作用域:ES5中只有全局和函数作用域,没有块级作用域,let会产生块级作用域。
    • var没有块级作用域的一些问题
        1. 内层变量会笼罩外层变量;
        1. 用来计数的循环变量泄露为全局变量;

es6/7有什么新个性?

箭头函数(不绑定本人的this),解构赋值,spread开展,块级作用域(let,const),promise异步解决方案,set(没有反复的值)/map数据结构,proxy拦截器

重要属性:class类(类继承extends,constructor,super)

es7: async(async,await)异步操作,返回promise对象,能够接着用.then办法来连贯;

es6长期死区?

在 ES6 中,let 和const 跟 var、class和function一样也会被晋升,只是在进入作用域和被申明之间有一段时间不能拜访它们,这段时间是长期死区(TDZ)

//console.log(aLet)  // would throw ReferenceErrorlet aLet;console.log(aLet); // undefinedaLet = 10;console.log(aLet); // 10

es6中的map和原生对象有什么区别?

原生对象的key只能是string类型的,map的key能够是任意值(object,array,function,undefind...)

map是一种更欠缺的hash构造实现;

map的实用场景,把不同的事件关联起来;、

class类

class类的根本介绍?

生成对象的模板

次要组成:

  • constructor:构造方法

    • 默认属性,也可手动增加
    • 间接指向“类”的自身,和es5的行为统一 //Person.prototype.constructor === Person
  • 实例办法
  • 静态方法
  • 公有办法、公有属性
  • new.target属性

特点:

  • 类外部定义的办法,都是不可枚举的(non-enumeerable),和构造函数不一样
//es6的类,可看作是构造函数的另一种写法class Person{}typeof Person  //"function"Person===Person.prototype.constructor //true

参考资料:

Class 的根本语法

class与一般构造函数有什么区别?

class实质应用prototype的原型链,只是一种语法糖;

在语法上更加贴合面向对象的语法,在实现继承上更新易读、易了解;

区别:

  • 【变量晋升】

    • 类:没有
    • 构造函数:有
  • 【调用】

    • 类:必须应用new调用,否则报错
    • 构造函数:可间接调用
  • 【严格模式】

    • 类:类和模块的外部,默认是严格模式,无需应用 use strict 关键词
    • 构造函数:无强制要求
//类不存在变量晋升new Person{}; //ReferenceErrorclass Person{}

在构造函数中调用super(props)的目标是什么?

es6语法 中,super指代父类的构造函数;

react外面就是指代 React.Component 的构造函数

在调用super() 之前,无奈在构造函数中应用this;在es2015中,子类必须在 constructor中调用super(),传递props给super() 的起因是便于能在constructor拜访this.props;

参考资料:

React构造函数中为什么要写 super(props)

Async/Await

对async await的了解,外部原理?

实质:async是Generator的语法糖;

async扭转有如下几个办法

  • 更好的语义化:async相当于*,await 相当于yield;
  • 返回值是promise,generator返回的是Iterator对象,更不便的应用then来操作
  • 内置执行器:async自带执行器,Generator须要依附执行器(每次都是执行g.next()办法);
  • 更广的适用性:async函数的await后盾能够是promise对象,也能够是原始类型的值;

async/await相比 promise的劣势?

  • 同步写法优雅:使解脱了then的链式调用带来的浏览累赘
  • 获取返回值不便:promise传递两头传十分麻烦,而async/await简直是同步的写法,更优雅
  • 错误处理敌对:async/await可应用成熟的 try/catch,promise的谬误捕捉十分冗余
  • 调试敌对:promise中的then应用调试器的步进(step-over)性能,调试器并不会进入后续的then代码块,因为调试器只能跟踪同步代码的【每一步】

promise

介绍下promise?

Promise是es6引入的一个新的对象,用来解决js中异步回调天堂的写法,并不是什么突破性的api,只是封装了异步回调函数;

使得异步写的更加优雅, 可读性更高,而且反对链式操作;

promise有几个状态?

Promise一共有三种状态

1.初始化,状态:pending

2.当调用resolve(胜利),状态:pengding=>fulfilled

3.当调用reject(失败),状态:pending=>rejected

promise外部实现原理?

Promise/A+标准

  1. pending:示意初始状态,能够转移到 fullfilled 或者 rejected 状态
  2. fulfilled:示意操作胜利,不可转移状态
  3. rejected:示意操作失败,不可转移状态
  4. 必须有一个 then 异步执行办法,then 承受两个参数且必须返回一个promise

实现思路

咱们定义Promise1对象,在对象外部创立status、reason、fullfilledCallbacks、rejectedCallbacks这四个属性,这些属性别离示意的意义为:

  1. reason:保留以后promise实例状态
  2. value:保留fullfilled之后的值
  3. reason:保留rejected后的起因
  4. fullfilledCallbacks: fullfilled回调队列
  5. rejectedCallbacks:rejected回调队列

咱们定义resolve和reject办法用于解决传进来的executor函数。在以后实例调用then办法时候去返回新的Promise1实例,并判断以后实例状态是否pendding,如果pendding,将传入的胜利和失败回调函数退出队列,在内部调用resolve或者reject时候,再次判断以后状态是否pendding,如果是,则批改以后实例状态为fullfilled或者rejected,并批量执行回调队列中的回调函数。

promise 状态流转过程

参考资料:

今日头条: 介绍下Promise,外部实现(一面)

图解 Promise 实现原理(一)—— 根底实现

promise和async解决失败有什么区别?

## promisefunction asyncTast(url){   return new Promise(resolve,reject) => {    }}## asynctry{}catch(e){console.log(e);}

如何设计promise.all?

总结 promise.all 的特点

1、接管一个 Promise 实例的数组或具备 Iterator 接口的对象,

2、如果元素不是 Promise 对象,则应用 Promise.resolve 转成 Promise 对象

3、如果全副胜利,状态变为 resolved,返回值将组成一个数组传给回调

4、只有有一个失败,状态就变为 rejected,返回值将间接传递给回调
all() 的返回值也是新的 Promise 对象

实现思路:

function promiseAll(promises) {  return new Promise(function(resolve, reject) {    if (!isArray(promises)) {      return reject(new TypeError('arguments must be an array'));    }    var resolvedCounter = 0;    var promiseNum = promises.length;    var resolvedValues = new Array(promiseNum);    for (var i = 0; i < promiseNum; i++) {      (function(i) {        Promise.resolve(promises[i]).then(function(value) {          resolvedCounter++          resolvedValues[i] = value          if (resolvedCounter == promiseNum) {            return resolve(resolvedValues)          }        }, function(reason) {          return reject(reason)        })      })(i)    }  })}

Promise 构造函数是同步执行还是异步执行,那么 then 办法呢?

promise构造函数是同步执行的,then办法是异步执行的

const promise = new Promise((resolve, reject) => {  console.log(1)  resolve()  console.log(2)})promise.then(() => {  console.log(3)})console.log(4)

参考资料:

Promise 构造函数是同步执行还是异步执行,那么 then 办法呢?

API

Map api?

Map 保留键值对,并且可能记住键的原始插入程序。任何值都能够作为一个或一个
  • Map的属性

    • size
  • Map的办法
    • 增:set({key:value}) //减少对象
    • 删:

      • -clear() //清空对象
      • delete(key) //删除对象
    • 改:
    • 查:

      • -get(key) //获取对象
      • has(key) //返回一个布尔值,判断Map实例是否蕴含键对应的值
    • 遍历:

      • forEach(callbackFn[,thisArg]) //删除对象
    • 其余:

      • keys() //返回类型:Iterator对象,获取keys列表
      • values() //返回类型:Iterator对象 ,返回一个新的Iteratror对象,它按插入程序蕴含了Map对象中每个元素的值

Set api?

set对象容许你存储任何类型惟一值,无论是原始值或者是对象援用

属性:

  • 长度:size

实例办法:(Set.prototype)

  • 创立: new Set(); new Set([1,2]);
  • 增(只反对增加在尾部):

    • 尾:只承受一个参数,但可链式调用, mySet.add(1).add(2)
  • 删:

    • 指定item : delete(value) //Array(value=item),Object (value=object)
    • 清空: clear()
  • 查:

    • 判断值是否存在: has(value) //Array(value=item),Object (value=object)
  • 遍历:

    • for循环:for(const item of set1){console.log(item);}
    • forEach: 无返回值