let obj = {
username: 'luwang',
age: 23
}
// let username = obj.username
// let age = obj.age
// console.log(username, age)
// let {username, age} = obj // 对象,因此需要以对象的形式来接收 只需要一个就写一个,不需要按顺序
// console.log(username, age)
let {age} = obj
console.log(age)
// [b, a] = [a, b]
let arr = [1, 3, 5,'abc', true]
// let [a, b, c, d, e] = arr
// console.log(a, b, c, d, e)
// let [a, b] = arr
// console.log(a, b)
let [,,a, b] = arr
console.log(a, b)
function foo({username, age}){ // {username, age} = obj
console.log(username, age)
}
foo(obj)
3、各种数据类型的扩展
(1) 字符串
模板字符串
作用:简化字符串的拼接
模板字符串必须用两个 "`" 包裹起来,ESC 下面那个键
变量的部分使用 ${xxx} 定义
let obj = {username: 'luwang', age: 23}
/*
* 之前的写法:简单拼串
* 缺点:可能会拼错,效率低。比如,url携带10个参数,动态拼起来
*/
let str = 'My name is ' + obj.username + ', age is '+ obj.age
console.log(str)
/*
* ES6提供的模板字符串
*/
str = `My name is ${obj.username} age is ${obj.age}`
// 定义一个点的坐标的构造函数
function Point(x, y){
this.x = x
this.y = y
}
let point = new Point(50, 20)
console.log(point) // Point {x: 50, y: 20}
// 忘记传参
let point1 = new Point()
console.log(point1) // Point {x: undefined, y: undefined}
/*
* 因此会有需求,在忘记传参的时候使用默认值
* 在形参的位置赋默认值
*/
function Point(x = 0, y = 0){
this.x = x
this.y = y
}
let point = new Point(50, 20)
console.log(point) // Point {x: 50, y: 20}
// 忘记传参,使用默认值
let point1 = new Point()
console.log(point1) // Point {x: 0, y: 0}
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.showMe = function() {
console.log(this.name)
}
let person = new Person('kobe', 39)
person.showMe()
console.log(person)
(2) class 定义类
在类中通过 constructor() 定义构造方法(相当于构造函数)
// 定义一个 Person 类
class Person { // 类声明
// const Person = class { // 类表达式,类表达式的名称是可选的
// 类的构造方法,只能有一个
constructor(name, age) { // constructor(){} 里面的参数是生成实例传入的参数
// 在构造方法中通过 this 给实例对象添加属性
this.name = name
this.age = age
}
// 在类中定义的方法,都是添加到类的原型对象上的
showMe(){
console.log(this.name) // this 指向实例对象,所以可以通过 this 来访问实例对象的属性
}
}
let person = new Person('kobe', 39) // new Person() 会自动调用 constructor() 构造方法,创建实例对象,并且将参数传递给 constructor() 构造方法
console.log(person)
person.showName()
// 父类
class Person{
constructor(name, age){
this.name = name
this.age = age
}
showMe(){
console.log('调用父类的方法')
console.log(this.name, this.age)
}
add(){
console.log('父类的一般方法')
}
}
let person = new Person('kobe', 39)
person.showMe()
// 子类:继承父类
class StarPerson extends Person{
constructor(name, age, salary){
// 如果子类中定义了构造方法,那么子类的构造方法中必须调用 super(),否则会报错
super(name, age) // 调用父类的构造方法,将参数传递给父类的构造方法
this.salary = salary // 子类自己的属性
}
showMe(){
// 可以通过 super 来调用父类的方法
super.add() // 调用父类的一般方法
console.log('子类的重写方法')
console.log(this.name, this.age, this.salary)
}
}
let p1 = new StarPerson('wade', 36, 10000000)
console.log(p1)
p1.showMe()
在一个构造方法中可以使用 super 关键字来调用父类的构造方法
在派生类中(子类),super() 必须要先调用,然后才能使用 this 关键字,否则会报错
super 关键字也可以用来调用父类的普通方法
extends 关键字用来实现类的继承,extends 后面跟父类的名称(也可以是内建对象)
(4) class 类的静态方法
通过 static 关键字来定义静态方法
静态方法是通过类来调用的,不能通过实例对象来调用
静态方法中的 this 指向类本身
// 定义一个 Person 类
class Person{
constructor(name, age){
this.name = name
this.age = age
}
showMe(){
console.log('调用 showMe 方法')
console.log(this.name, this.age)
}
// 静态方法
static showName(){
console.log('调用 Person 的静态方法')
console.log(this) // this 指向类本身
}
}
let person = new Person('kobe', 39)
person.showMe()
Person.showName() // 通过类来调用静态方法
(5) class 类的 getter 和 setter 方法
通过 get 和 set 关键字来定义 getter 和 setter 方法
getter 和 setter 方法是通过实例对象来调用的
getter 和 setter 方法中的 this 指向实例对象
// 定义一个 Person 类
class Person{
constructor(name, age){
this.name = name
this.age = age
}
showMe(){
console.log('调用 showMe 方法')
console.log(this.name, this.age)
}
// 静态方法
static showName(){
console.log('调用 Person 的静态方法')
console.log(this) // this 指向类本身
}
// getter 方法
get info(){
console.log('调用 getter 方法')
return this.name + ' ' + this.age
}
// setter 方法
set info(value){
console.log('调用 setter 方法')
let arr = value.split(' ')
this.name = arr[0]
this.age = arr[1]
}
}
let person = new Person('kobe', 39)
person.showMe()
Person.showName() // 通过类来调用静态方法
console.log(person.info) // 通过实例对象来调用 getter 方法
person.info = 'wade 36' // 通过实例对象来调用 setter 方法
console.log(person.info)
(6) class 类的静态属性
通过 static 关键字来定义静态属性
静态属性是通过类来调用的,不能通过实例对象来调用
静态属性中的 this 指向类本身
// 定义一个 Person 类
class Person{
constructor(name, age){
this.name = name
this.age = age
}
showMe(){
console.log('调用 showMe 方法')
console.log(this.name, this.age)
}
// 静态方法
static showName(){
console.log('调用 Person 的静态方法')
console.log(this) // this 指向类本身
}
// getter 方法
get info(){
console.log('调用 getter 方法')
return this.name + ' ' + this.age
}
// setter 方法
set info(value){
console.log('调用 setter 方法')
let arr = value.split(' ')
this.name = arr[0]
this.age = arr[1]
}
// 静态属性
static info = '这是一个静态属性'
}
let person = new Person('kobe', 39)
person.showMe()
Person.showName() // 通过类来调用静态方法
console.log(person.info) // 通过实例对象来调用 getter 方法
person.info = 'wade 36' // 通过实例对象来调用 setter 方法
console.log(person.info)
console.log(Person.info) // 通过类来调用静态属性
(7) 私有类字段(属性和方法)
私有类字段是指类中只能在类的内部访问的字段(属性和方法)
私有类字段可以通过在字段名前面添加 # 来定义
// 定义一个 Person 类
class Person{
constructor(name, age){
this.name = name
this.age = age
}
showMe(){
console.log('调用 showMe 方法')
console.log(this.name, this.age)
}
// 静态方法
static showName(){
console.log('调用 Person 的静态方法')
console.log(this) // this 指向类本身
}
// getter 方法
get info(){
console.log('调用 getter 方法')
return this.name + ' ' + this.age
}
// setter 方法
set info(value){
console.log('调用 setter 方法')
let arr = value.split(' ')
this.name = arr[0]
this.age = arr[1]
}
// 静态属性
static info = '这是一个静态属性'
// 私有类字段
#money = 10000000
#showMoney(){
console.log('调用私有类方法')
console.log(this.#money)
}
}
let person = new Person('kobe', 39)
person.showMe()
Person.showName() // 通过类来调用静态方法
console.log(person.info) // 通过实例对象来调用 getter 方法
person.info = 'wade 36' // 通过实例对象来调用 setter 方法
console.log(person.info)
console.log(Person.info) // 通过类来调用静态属性
console.log(person.money) // undefined
person.showMoney() // 报错
let set = new Set([1, 2, 4, 3, 4, 5])
for(let i of set){
console.log(i)
}
// 可以用 Set 给数组去重
let arr = [1,2,4,5,5,6,2]
let arr1 = arr
arr = [] // 保留数组类型
let set = new Set(arr1)
for(let i of set){
arr.push(i)
}
console.log(arr)
例如
// 模拟指针对象(遍历器对象)
function myIterator(arr){// Iterator接口
let nextIndex = 0 // 记录指针的位置
return{
next: function(){// 遍历器对象
return nextIndex < arr.length ? {value: arr[nextIndex++], done: false} : {value: undefined, done: true}
}
}
}
// 准备一个数据
let arr =[1,4,65,'abc']
let iteratorObj = myIterator(arr)
console.log(iteratorObj.next()) // {value: 1, done: false}
console.log(iteratorObj.next()) // {value: 4, done: false}
console.log(iteratorObj.next()) // {value: 65, done: false}
console.log(iteratorObj.next()) // {value: "abc", done: false}
console.log(iteratorObj.next()) // {value: undefined, done: true}
// 将iterator接口部署到指定的数据类型上,可以使用for of去循环遍历
// 数组、字符串、argument、set容器、map容器
for(let i of arr){
console.log(i)
}// 1 4 65 abc
let str = 'abcdefg'
for(let i of str){
console.log(i)
}// a b c d e f g
function fun(){
for(let i of arguments){
console.log(i)
}
}
fun(1,4,5,'abc') // 1 4 5 abc
// let obj = {username:'kobe', age: 39}
// for(let i of obj){
// console.log(i)
// }// Uncaught TypeError: obj is not iterable 不可迭代
title: 一文总结 ES 新特性 date: 2020-04-28 23:33 updated: 2020-04-28 23:33 cover: //cdn.wallleap.cn/img/pic/cover/202302NoyYdY.jpg category: 技术杂谈 tags:
前端 description: 一文总结 ES 新特性
总结并列出 ES 5 及之后的新特性
一、理解 ES
全称: ECMAScript (/ˈɛkməskrɪpt/)
JS 包含三个部分:
ECMAScript(JS 基础、核心部分)
扩展 → 浏览器端
扩展 → 服务器端
ES 的几个重要版本
二、ES 5 新特性
ES 5 对 JS 进行了修修补补,大概可以分为以下几类:
1、严格模式
理解:
目的/作用:
使用:
"use strict"
语法和行为改变:
var
(没有隐式的全局变量了,你要创建全局变量必须是显式的)this
关键字指向全局对象(window
或global
),不管是fn()
在全局调用还是apply()
、call()
默认都不会指向全局对象eval
作用域,更安全with
arguments
只保存原始参数,对形参的赋值不会对arguments
有影响,不准用arguments.caller
和arguments.callee
var a = 015
会报错writeable
是false
,给这个属性赋值会报错configurable
是false
,则delete
这个属性会报错2、JSON 序列化和反序列化
JSON.stringify(obj/arr)
JS 对象(数组)转换为 JSON 数据(字符串)JSON.parse(json)
JSON 字符串转换为 JS 对象(数组)3、Object 扩展
ES 5 给 Object 扩展了一些静态方法
Object.keys()
,Object.create()
,Object.defineProperty
,Object.defineProperties
,Object.getOwnPropertyDescriptor()
,Object.getOwnPropertyNames(obj)
,Object.getPrototypeOf(obj)
Object.seal()
,Object.freeze()
,Object.preventExtensions()
,Object.isSealed()
,Object.isFrozen()
,Object.isExtensible()
常用的两个:
create
Object.create(prototype[, descriptors])
:创建一个新的对象,返回值是新对象作用:使用现有的对象来作为新创建对象的原型
为新的对象指定新的属性,并对属性进行描述
value
:指定值writable
:标识当前属性值是否是可修改的,默认为false
configurable
:标识当前属性是否可以被删除,默认为false
enumerable
:标识当前属性是否能用for in枚举,默认为false
defineProperties
Object.defineProperties(object, descriptors)
:为指定对象定义扩展多个属性惰性求值:点击才给值(什么时候要什么时候给),会再次调用 get 方法
对象本身也有两个方法:
4、Array 扩展
Array.isArray(arr)
:判断一个对象arr
是否是数组Array.prototype.indexOf(value)
:得到值在数组中的第一个下标Array.prototype.lastIndexOf(value)
:得到值在数组中的最后一个下标Array.prototype.forEach(function(item, index, array){}[, asThis])
:遍历数组,返回值是undefined
Array.prototype.map(function(item, index, array){}[, asThis])
:遍历数组返回一个新的数组(每一项是回调函数的返回值)Array.prototype.filter(function(item, index, array){}[, asThis])
:遍历过滤出一个子数组,返回一个由条件为true
的元素组成的新数组Array.prototype.reduce(function(accumulator, item, index, array)[, initValue])
:Array.prototype.reduce 对数组中的每个元素按序执行一个提供的回调函数,每次执行回调函数会将之前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值Array.prototype.reduceRight
:从右到左Array.prototype.some(function(){item, index, array}[, asThis])
:数组中是否至少有一个元素符合回调函数给定的条件,有则返回true
,没有返回false
Array.prototype.every(function(item, index, array){}[, asThis])
:判断一个数组内的所有元素是否都能通过指定函数的测试,返回布尔值(回调函数有三个参数,第一个为当前遍历的对象、第二个为当前的下标、第三个为数组本身,方法还接受第二个参数,将作为this
)5、Function 扩展
函数新增
bind
方法,Function.prototype.bind(asThis)
,将函数内的this
绑定为asThis
,并将函数返回强制绑定
this
使用call
/apply
和bind
this
的值通过函数调用的时候确定fn
,this
是默认值,undefined
或window
obj.x.fn()
,this
是前面调用的内容obj.x
,例如btn.addEventListener
里面this
就是btn
call(asThis, args)
或apply(asThis, [args])
,this
就是传的asThis
new fn(args)
,this
就是新创建的对象fn.bind(asThis, args)
:指定函数中的this
,并返回函数(不会立即调用),一般用在回调函数绑定其他对象的this
fn.call(asThis, args)
:指定函数中的this
,并调用函数fn.apply(asThis, [args])
:指定函数中的this
,并调用函数总结:三个都可以给
fn
指定this
,bind
不会调用fn
,call
和apply
都会调用fn
,call
的其他参数依次以逗号分隔,apply
的其他参数以数组形式传递6、Date扩展
Date.now()
:得到当前时间值,之前new Date()
Date.prototype.toISOString
:新增方法,会返回一个 ISO 格式的字符串(YYYY-MM-DDTHH:mm:ss.sssZ
)new Date(string)
和Date.parse(string)
新增对 ISO 格式的支持7、其他
String.prototype.trim
,去除字串头尾空格{a: 1, b: 2,}
{if: 1, else: 2}
NaN
、Infinity
、undefined
都是常量了,不可更改parseInt()
第二个参数默认为 10/regexp/
正则字面量每次都会产生一个新的对象三、ES 6 新特性
ES 6 新增了很多特性,让 JS 变得非常好用
1、2 个声明变量的新关键字
ES 6 中新增了块作用域,
{}
包裹的地方就是一个块,ES 5 中没有块级作用域(只有全局和函数作用域)let 关键字
作用:与 var 相似,用于声明一个变量
特点:
应用:
循环遍历加监听
const 关键字
作用:定义一个常量
特点
应用
保存不用改变的数据
2、变量(对象)的解构赋值
理解:
从对象或数组中提取数据,并赋值给多个变量
将包含多个数据的对象/数组一次赋值给多个变量
数据源:对象/数组
目标:
{a, b}
/[a, b]
对象的解构赋值:
let {n, a} = {n:'tom', a:12}
把对象中的值赋值出来(根据属性名 key)数组的解构赋值:
let[a, b] = [1, 'luwang']
(根据下标)用途:数组匹配、对象匹配、参数匹配(给多个形参赋值)
3、各种数据类型的扩展
(1) 字符串
模板字符串
${xxx}
定义字符串支持 Unicode
String.fromCodePoint
String.prototype.codePointAt
新增一些方法
String.prototype.includes(str)
:判断是否包含指定的字符串String.prototype.startsWith(str)
:判断是否以指定字符串开头String.prototype.endsWith(str)
:判断是否以指定字符串结尾String.prototype.repeat(count)
:重复指定次数(2) 数值
二进制与八进制表示法:二进制用
0b
,八进制用0o
新增方法:
Number.EPSILON
:最小精度Number.isFinite(i)
:判断是否是有限大的数字Number.isNaN(i)
:判断是否是NaNNumber.isInteger(i)
:判断是否是整数Number.isSafeInteger(i)
Number.parseInt(str)
:将字符串转换为对应的数值Math.acosh
、Math.hypot
、Math.imul
、Math.sign
Math.trunc(i)
:直接去除小数部分(3) 对象
简化的对象写法(短语法)
属性名支持表达式,需要用方括号括起来:
属性简写和解构赋值结合使用:
const {id, name} = user
){id: id, name: name}
){data: res}
等同于{data: data}
,data
是一个变量,res
是一个新的变量,可以用于解构赋值(获取到等号右边的data.data
)复制对象
Object.assign(target, source1, source2..)
:将源对象的属性复制到目标对象上判断是否相等
Object.is(v1, v2)
:判断2个数据是否完全相等__proto__
属性__proto__
属性:隐式原型属性。ES 6 中能直接操作__proto__
属性,但是不推荐使用(4) 数组
Array.from(v)
:将伪数组对象或可遍历对象转换为真数组Array.of(v1, v2, v3)
:将一系列值转换成数组find(function(value, index, arr){return true})
:找出第一个满足条件返回true的元素findIndex(function(value, index, arr){return true})
:找出第一个满足条件返回 true 的元素下标fill
:填充数组copyWithin
:复制数组中一系列元素到同一数组指定的起始位置entries
:返回一个新的 Array Iterator 对象,该对象包含数组中每个索引的键/值对keys
:返回一个新的 Array Iterator 对象,该对象包含数组中每个索引的键values
:返回一个新的 Array Iterator 对象,该对象包含数组中每个索引的值(5) 函数
Ⅰ、箭头函数
让函数写法更简便
基本语法:
const fn = () => console.log('xxxx')
箭头前的()不能省略i => i+2
可以省略(i,j) => i+j
()不能省略{}
包围使用场景:多用来定义回调函数
特点:
this
,箭头函数的this
不是调用的时候决定的,而是在定义的时候所处的对象就是它的this
this
看外层是否有函数this
是外层函数的this
this
是window
Ⅱ、参数处理
3 点运算符/点点点运算符
第一种用法:在函数中,rest(可变)参数
...
来表达,取代arguments
的使用arguments
灵活,只能是最后部分形参参数arguments
是伪数组,有length
,但是没有数组的一般方法,不能使用forEach
遍历callee
是arguments
的一个属性,等于函数本身,递归的时候可以写为:arguments.callee()
第二种用法——扩展/展开运算符,可以分解出数组或对象中的数据
Ⅲ、形参的默认值
(6) 正则表达式
u
标记)y
标记,支持粘滞匹配4、新增数据类型
(1) Symbol 类型
前言:ES 5 中对象的属性名都是字符串,容易造成重名,污染环境
概念:ES 6 中添加了一种原始数据类型 symbol(已有的数据类型:String、Number、boolean、null、undefined、对象)
特点:
使用:
(2) Set/Map 容器结构
容器: 能保存多个数据的对象,同时必须具备操作内部数据的方法
任意对象都可以作为容器使用,但有的对象不太适合作为容器使用(如函数)
Set 的特点:保存多个 value,value 是不重复 ====>数组元素去重
Map 的特点:保存多个 key-value,key 是不重复,value 是可以重复的
API:
Set()
:创建一个空的 Set 容器Set(arr)
:创建一个 Set 容器,同时将 arr 数组(其中 arr 是一维数组)中的元素添加到 Set 容器中(去重)add(value)
:向 Set 容器中添加一个 valuedelete(value)
:删除 Set 容器中指定的 valueclear()
:清空 Set 容器中的所有元素has(value)
:判断 Set 容器中是否存在指定的 valuesize
:获取 Set 容器中元素的个数Map()
:创建一个空的 Map 容器Map(arr)
:创建一个 Map 容器,同时将 arr 数组(其中 arr 是二维数组)中的元素添加到 Map 容器中(去重)set(key, value)
:向 Map 容器中添加一对 key-valueget(key)
:获取 Map 容器中指定 key 对应的 valuedelete(key)
:删除 Map 容器中指定的 key-valueclear()
:清空 Map 容器中的所有元素has(key)
:判断 Map 容器中是否存在指定的 keysize
:获取 Map 容器中元素的个数(3)WeakSet 和 WeakMap 类型
WeakSet
对象是一些对象值的集合。且其与Set
类似,WeakSet
中的每个对象值都只能出现一次。在WeakSet
的集合中,所有对象都是唯一的。WeakSet
只能是对象的集合,而不能像Set
那样,可以是任何类型的任意值。WeakSet
持弱引用:集合中对象的引用为弱引用。如果没有其他的对WeakSet
中对象的引用,那么这些对象会被当成垃圾回收掉。Object
类型。 原始数据类型 是不能作为 key 的(比如Symbol
)。WeakMap
持有的是每个键对象的“弱引用”,WeakMap
的 key 是不可枚举的(4)TypedArray 类型
5、class 类
ES6 中新增的语法,用于实现面向对象编程
通过
class
关键字定义类,实现类的继承(1) 之前实现继承
回顾:原型、构造函数、构造函数+原型——继承
(2)
class
定义类在类中通过
constructor()
定义构造方法(相当于构造函数)(3) class 类的继承
一般方法:xxx () {}
用 extends 来定义子类(实现类的继承)
用 super() 来调用父类的构造方法
子类方法自定义:将从父类中继承来的方法重新实现一遍(重写从父类继承的一般方法)
super
关键字来调用父类的构造方法super()
必须要先调用,然后才能使用this
关键字,否则会报错super
关键字也可以用来调用父类的普通方法extends
关键字用来实现类的继承,extends
后面跟父类的名称(也可以是内建对象)(4) class 类的静态方法
通过 static 关键字来定义静态方法
静态方法是通过类来调用的,不能通过实例对象来调用
静态方法中的 this 指向类本身
(5) class 类的 getter 和 setter 方法
通过 get 和 set 关键字来定义 getter 和 setter 方法
getter 和 setter 方法是通过实例对象来调用的
getter 和 setter 方法中的 this 指向实例对象
(6) class 类的静态属性
通过 static 关键字来定义静态属性
静态属性是通过类来调用的,不能通过实例对象来调用
静态属性中的 this 指向类本身
(7) 私有类字段(属性和方法)
私有类字段是指类中只能在类的内部访问的字段(属性和方法)
私有类字段可以通过在字段名前面添加
#
来定义6、Promise 对象
理解:
Promise 对象代表了某个将要发生的事件(通常是一个异步操作)
ES 6 的 Promise 是一个构造函数,用来生成 promise 实例
解决回调地狱(回调函数的层层嵌套,编码是不断向右扩展,阅读性很差);有了 promise 对象,可以将异步操作以同步的流程表达出来,避免了层层嵌套的回调函数(回调地狱)
能以同步编码的方式实现异步调用
在 ES 6 之前原生的 JS 中是没这种实现的,一些第三方框架(jQuery)实现了 Promise
promise 对象的 3 个状态:
在同一个 Promise 中只能 pending 到 pending、pending 到 fullfilled、pending 到 rejected,不能成功之后又失败或失败之后在成功
应用:
(1) Promise 的基本使用
ES 6 中定义实现 API(使用 Promise 基本步骤):
例子:
例如:新闻、新闻的评论,只发新闻的内容;在接着根据新闻的 id 拿取这个新闻下的评论
new Promise()
创建一个新的 Promise 对象resolve()
将 Promise 对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去reject()
将 Promise 对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去then()
:添加状态改变时的回调函数catch()
:添加状态改变时的回调函数finally()
:添加状态改变时的回调函数all()
:将多个 Promise 实例,包装成一个新的 Promise 实例race()
:将多个 Promise 实例,包装成一个新的 Promise 实例resolve()
:将现有对象转为 Promise 对象reject()
:返回一个新的 Promise 实例,该实例的状态为 rejected(2) Promise 的链式调用
生成的 Promise 对象可以进行链式调用,即 then() 方法返回的是一个新的 Promise 对象,可以继续调用 then() 方法
7、Iterator 迭代器
概念:iterator 是一种接口机制,为各种不同的数据结构提供统一的访问机制
作用:
工作原理
next
方法,指针自动指向数据结构的第一个成员next
方法,指针会一直往后移动,直到指向最后一个成员next
方法返回的是一个包含 value 和 done 的对象{value: 当前成员的值, done: 布尔值}
原生具备 Iterator 接口的数据,可用 for...of 遍历
扩展理解
for-of 循环:可以遍历任何容器(Set、Map)、数组、对象、伪/类对象、字符串、可迭代的对象
例如
8、Generator 生成器
概念:
特点:
function 与函数名之间有一个星号
内部用 yield 表达式来定义不同的状态
例如:
generator 函数返回的是指针对象,而不会执行函数内部逻辑
调用 next 方法函数,内部逻辑开始执行,遇到 yield 表达式停止,返回
{value: yield后的表达式结果/return后的返回结果(如果没写,返回undefined),done: boolean值(后面还有返回false,没有返回true)}
再次调用 next 方法会从上一次停止时的 yield 处开始,直到最后
yield 语句返回结果通常为 undefined,当调用 next 方法时传参内容会作为启动时 yield 语句的返回值
补充:
例如:
9、模块
导入
import
语句用于导入由另一个模块导出的绑定import
语句只能在声明了type="module"
的script
的标签中使用import()
,它不需要依赖type="module"
的 script 标签语法:
导出
在创建 JavaScript 模块时,
export
语句用于从模块中导出实时绑定的函数、对象或原始值,以便其他程序可以通过import
语句使用它们10、其他
元编程
尾调用优化
五、ES 2016
新增了两个新特性
1、指数操作
指数运算符(幂):
**
2、数组新方法
Array.prototype.includes(value)
: 判断数组中是否包含指定 value六、ES 2017
1、async/await 函数
概念:真正意义上去解决异步回调的问题,同步流程表达异步操作
本质:Generator 的语法
语法:
特点:
*
,await 取代 Generator 的 yield获取新闻内容案例
改进一下,由于这种写法 error 并不会显示错误信息
给个模板
2、对象
Object.values
:返回对象的所有值Object.entries
:返回对象的所有键值对3、字符串填充
padStart()
、padEnd()
分别可以在字符串位数不足的时候向头部和尾部进行填充内容第一个参数是总位数,第二个参数为位数不足时填充的内容
例如:
4、参数可以有多余的逗号
5、其他
getOwnPropertyDescriptors
:获取对象的所有属性,包括不可枚举的属性后续好用的新特性
问号
可选链:
?.
双问号:
??
两个结合使用
由于现在开发都会用到 Babel 转译代码,所以可以放心使用这些新特性