ES6+
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(): 向生成器抛出一个错误
参考资料:
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
参考资料:
箭头函数与普通函数区别?
箭头函数的优点
语法更简洁
不用写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,之后永远不会修改。避免this指向不确定的问题,更方便的管理作用域
箭头函数其他的一些特性:
不能作为构造函数:不能使用new关键词创建构造函数,因为它没有自己的this。
没有自己的 arguments对象:但是可以访问外部的arguments对象
没有原型属性:箭头函数没有 prototype属性,所以不能用作构造函数
参考资料:
什么是严格模式(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 关键词,直接定义
参考资料:
介绍下js的装饰器(decorators)?
Decorator 就是一种动态地往一个类中添加新的行为的设计模式,它可以在类时,扩展一个类的功能,并且 去修改类本身的属性和方法,使其可以在不同类之间更灵活的共用一些属性和方法;
修饰模式(Decortaor),是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。修饰模式相比生成子类更加灵活,这样可以给某个对象而不是整个类添加一些功能
用法:
装饰类
装饰属性
3)多个装饰器
参考资料:
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/#docs/module-loader#ES6-%E6%A8%A1%E5%9D%97%E4%B8%8E-CommonJS-%E6%A8%A1%E5%9D%97%E7%9A%84%E5%B7%AE%E5%BC%82
/** AMD写法 **/
/** CMD写法 **/
js中let ,var 区别,let有什么优点?
相同点:都是定义变量的,都可以修改
let 优点:
不能重复声明:var可以重复声明,避免变量被覆盖
不存在变量提升:let 不存在变量提升,一定要先定义再使用。未定义的变量会报
存在暂时性死区: 只要块级作用域内存在let/const命令,它所声明的变量便绑定在这个区域,不再受外部影响
拥有块级作用域: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)。
ES6中的map和原生对象有什么区别?
原生对象的key只能是string类型的,map的key可以是任意值(object,array,function,undefind...)
map是一种更完善的hash结构实现;
map的适用场景,把不同的事件关联起来;、
介绍下ES6中的Symbol,它有哪些运用场景?
symbol是ES6中新增的一种基本数据类型,通过typeof symbol()可以发现,输出的是symbol。
symbol最大的特点返回值的唯一性,即使传入相同的参数(参数主要有来在控制来做区分,备注用的)。
所以基于这个特性,Symbol 可以用在以下几个场景。
作为对象的唯一值
switch作为唯一的枚举
Symbol需要注意的点
Symbol()函数不能使用new命令,否则会报错。 //这个和其他基本类型都不一样,比始:String, Number, Boolean等
Symbol作为属性名时,不能通过以前的api直接获取,比如:Object.keys(), Object.getOwnPropertyNames()。甚至是JSON.stringify()。但是,它也不是私有属性,有一个Object.getOwnPropertySymbols方法,可以获取指定对象所有的Symbol属性名。
介绍下ES6中的Proxy对象,它有哪些使用场景?
Proxy的字面意思是代理器,任何对对象(对象,数组,函数等都可以)的操作(包括:访问,写入等操作)都会进入这一层的拦截。可以在这一层添加一些自定义的操作。
比始拦截后的一些操作,方法复写与增强
增加日志记录
提供友好提示和阻止特定操作 // 读取不存在的属性时,自定义报错信息。不能删除特定的属性等。
读取负索引的值
设置真正的私有属性,私有的定义:不能访问,不能修改,不能遍历。 // 一般约定以 _ 开头key为私有属性
参考资料
https://weread.qq.com/web/reader/2ba32920720a57e92ba5389ka4a32da02aba4a042cf4e81
什么是可迭代对象,它有什么用?
for of有什么用,和for in有什么区别?
class类
class类的基本介绍?
生成对象的模板
主要组成:
constructor:构造方法
默认属性,也可手动添加
直接指向“类”的本身,和es5的行为一致 //Person.prototype.constructor === Person
实例方法
静态方法
私有方法、私有属性
new.target属性
特点:
类内部定义的方法,都是不可枚举的(non-enumeerable),和构造函数不一样
参考资料:
class与普通构造函数有什么区别?
class本质使用prototype的原型链,只是一种语法糖;
在语法上更加贴合面向对象的语法,在实现继承上更新易读、易理解;
区别:
【变量提升】
类:没有
构造函数:有
【调用】
类:必须使用new调用,否则报错
构造函数:可直接调用
【严格模式】
类:类和模块的内部,默认是严格模式,无需使用 use strict 关键词
构造函数:无强制要求
在构造函数中调用super(props)的目的是什么?
es6语法 中,super指代父类的构造函数;
react里面就是指代 React.Component 的构造函数
在调用super() 之前,无法在构造函数中使用this;在es2015中,子类必须在 constructor中调用super(),传递props给super() 的原因是便于能在constructor访问this.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和async处理失败有什么区别?
如何设计promise.all?
总结 promise.all
的特点
1、接收一个 Promise
实例的数组或具有 Iterator
接口的对象,
2、如果元素不是 Promise
对象,则使用 Promise.resolve
转成 Promise
对象
3、如果全部成功,状态变为 resolved
,返回值将组成一个数组传给回调
4、只要有一个失败,状态就变为 rejected
,返回值将直接传递给回调 all()
的返回值也是新的 Promise
对象
实现思路:
Promise 构造函数是同步执行还是异步执行,那么 then 方法呢?
promise构造函数是同步执行的,then方法是异步执行的
参考资料:
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: 无返回值
最后更新于