前言:
想零碎学习前端面试题,强烈推荐浏览 在线电子书(反对手机版,不断更新) 。
本书特点:零碎全面(涵盖前端核心技术点),简洁,针对性强(针对面试场景设计)。
欢送在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 模块有什么区别?
罕用的模块化办法:
模块名 | 导出模块 | 引入模块 | 加载形式 | 阐明 |
---|---|---|---|---|
ES6 | export | import | 动态加载 | 输入的援用,动态援用,只读属性 |
commonjs | module.exports | require | 动静援用 | 输入值的浅拷贝对象,动静加载,可读可写。nodejs中的规范 |
AMD(requirejs) | define | require | 异步 | 依赖前置,提前执行(在模块定义的时候就要引入) |
CMD(sea.js) | define | require(["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没有块级作用域的一些问题
- 内层变量会笼罩外层变量;
- 用来计数的循环变量泄露为全局变量;
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+标准
- pending:示意初始状态,能够转移到 fullfilled 或者 rejected 状态
- fulfilled:示意操作胜利,不可转移状态
- rejected:示意操作失败,不可转移状态
- 必须有一个 then 异步执行办法,then 承受两个参数且必须返回一个promise
实现思路
咱们定义Promise1对象,在对象外部创立status、reason、fullfilledCallbacks、rejectedCallbacks这四个属性,这些属性别离示意的意义为:
- reason:保留以后promise实例状态
- value:保留fullfilled之后的值
- reason:保留rejected后的起因
- fullfilledCallbacks: fullfilled回调队列
- 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: 无返回值