前言:
想零碎学习前端面试题,强烈推荐浏览 在线电子书(反对手机版,不断更新)。
本书特点:零碎全面(涵盖前端核心技术点),简洁,针对性强(针对面试场景设计)。
欢送在 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) 装璜类
@FooDecorator
class Foo {
}
function FooDecorator(target){// target 就是这个 class 的原型对象}
2) 装璜属性
// 给 MyClass 所有实例的 getType 属性设置为仅为可读不可更改的属性 readonly
class 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 办法会在控制台输入 hello
function 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 ReferenceError
let aLet;
console.log(aLet); // undefined
aLet = 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{}; //ReferenceError
class 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 解决失败有什么区别?
## promise
function asyncTast(url){return new Promise(resolve,reject) => {}}
## async
try{}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: 无返回值