ES6重点-1
字符串新增方法
padStart
用于字符串长度补全,如果某个字符串长度不够指定长度会在头部或尾部补全
console.log('xxx'.padStart(4, 'ab')); console.log('x'.padStart(4, 'ab')); //补全位数,有需要会重复或截取 console.log('x'.padStart(4)); // 不传第二个参数默认使用空格补全 console.log('xxx'.padStart(2)); // 补全后的长度小于源字符串长度则不做任何改变 // abax // axxx // x // xxx
padEnd
和
padStart
效果相反,从尾部开始补全console.log('x'.padEnd(5, 'abc')); console.log('x'.padEnd(4)); console.log('xxx'.padEnd(2)); console.log('xxx'.padEnd(4, 'ab')); // xabca // x // xxx // xxxa
对象新增扩展
链判断运算符
在ES5中,取对象属性时,往往需要判断以下该对象是否存在。如下
const name = (store && store.state && store.state.user && store.state.user.name) || "tom"
这种层层判断过于麻烦,因此ES2020引入链判断运算符
?.
const name = store?.state?.user?.name
如果左侧的对象为
null
或undefined
则直接返回undefined
,不再往下运算null
判断运算符独去对象属性时,如果某个属性的值时
null
或undefined
,有时需要为它们指定默认值。常见做法是通过||
运算符指定默认值const name = user.name || "tom" const age = user.age || 20
原意是属性值为
null
或undefined
时默认值就生效,但当user.name
为空串或user.age
为0时默认值也会生效为此ES2020引入新的
null
判断运算符??
const name = user.name ?? "tom" const age = user.age ?? 20
对象新增方法
Object.is
用来替代
==
和===
==
会进行自动类型转换,===
在比较+0和-0时返回true
,NaN
不等于自身Object.assign
用于对象合并
- 只拷贝源对象的自身、可枚举属性(含Symbol)
- 浅拷贝
- 同名属性会被覆盖
- 除首参数外(
null
、undefined
会报错),非对象会被转换为对象
Object.keys
返回对象自身的、可遍历的属性的键名数组
Object.fromEntries/Object.entries
Object.fromEntries
将一个键值对数组转换为一个对象,适合将Map
转换为Object
Object.entries
逆操作,用于将Object
转换为键值对数组
Array扩展
Array.of
弥补数组构造函数
Array()
的不足。因为参数个数的不同,会导致Array()
的行为有差异Array() //[] Array(3) //[ , , ] Array(3, 4, 5) //[3, 4, 5] Array.of() // [] Array.of(3) //[3] Array.of(3, 4, 5) //[3, 4, 5]
Array.prototype.copyWithin()
在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员)
Array.prototype.copyWithin(target, start = 0, end = this.length) [1, 2, 3, 4, 5].copyWithin(0, 3) // [4, 5, 3, 4, 5] [1, 2, 3, 4, 5].copyWithin(0, 3, 4) // [4, 2, 3, 4, 5]
Array.prototype.flat() && Array.prototype.flatMap()
flat()
用于将数据降维,参数为降低的维数(默认为1),如果不管有多少层维,都要转为一维数组,可使用Infinity
关键字作为参数如果原数组有空位
flat()
会跳过[1, 2, [1, 2]].flat() // [1, 2, 1, 2] [1, 2, [1, 2], [1, [2]]].flat() // [1, 2, 1, 2, 1, [2]] [1, 2, [1, 2], [1, [2]]].flat(2) // [1, 2, 1, 2, 1, 2] [1, 2, [1, 2], [1, [2]]].flat(Infinity) // [1, 2, 1, 2, 1, 2]
flatMap()
相当于Array.prorotype.Map
+Array.prorotype.flat
[1, 2, 3].flatMap(x => [x, x * 2]) // [1, 2, 2, 4, 3, 6] [1, 2, 3].flatMap(x => x * 2) // [2, 4, 6]
iterator
WHAT
遍历器(iterator
)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署了iterator
接口,就可以完成遍历操作
WHY
JavaScript原有的表示集合的数据结构主要是数组(Array)和对象(Object),ES6又添加了Map
、Set
。这样就有了四种数据集合,用户可以组合使用它们,定义自己的数据结构,比如数组的成员是Map
,Map
的成员是对象。这样需要一种统一的接口机制来处理不同的数据结构
主要作用
为各种数据结构提供一个统一的、简便的访问接口
使得数据结构的成员能够按某种次序排列
为
for...of
所使用适合遍历Array,既有
forEach
的简洁又有for
的break
、return
、continue
HOW
iterator
的遍历过程
- 创建一个指针对象,指向当前的数据结构的起始位置。也就是说遍历器对象本质上就是一个指针对象
- 第一次调用指针对象的
next
方法,可以将指针指向数据结构的第一个成员 - 第二次调用指针对象的
next
方法,指针就指向数据结构的第二个成员 - 不断调用指针对象的
next
方法,直到它指向数据结构的结束位置
每一次调用next
方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含value
和done
两个属性的对象,其中value
属性是当前成员的值,done
属性是一个布尔值,表示是否遍历结束
ES6规定,默认的iterator
接口部署在数据结构的Symbol.iterator
属性,或者说,一个数据结构只要具有Symbol.iterator
属性,就可以认为是可遍历的(iterable
)
const obj = {
data: ['hello', 'world'],
[Symbol.iterator](): {
const self = this
let index = 0
return {
next() {
if (index < self.data.length) {
return {
value: self.data[index++]
done: false
}
}
return {
value: undefined,
done: true
}
}
}
}
}
原生具备iterator接口的数据结构:Map、Array、Set、String、TypedArray、arguments、NodeList对象
let VS const
在let和const之间,建议优先使用const,尤其是在全局环境。const优于let的几个原因:
- const可以提醒阅读程序的人,这个变量不应该改变
- const比较符合函数式编程思想,运算不改变值,只是新建值,而且这样也有利于将来的分布式计算
- JavaScript编译器会对const进行优化
- 长远来看,JavaScript可能会有多线程的实现,这时let表示的变量只应出现在单线程运行的代码中,不是多线程共享的,这样有利于线程安全
// bad
var a = 1, b = 2, c = 3
// good
const a = 1;
const b = 2;
const c = 3;
// best
const [a, b, c] = [1, 2, 3]
generator
ES6提供的一种异步编程解决方案
形式上,generator
函数是一个状态机,封装了多个内部状态。执行generator
函数会返回一个遍历器对象。
语法上,generator
函数是一个普通函数。function
关键字与函数名之间有一个*
;函数体内部使用yield
表达式定义不同的内部状态
与普通函数不同,generator函数被调用后并不执行,返回的是一个指向内部状态的指针对象,也就是遍历器对象。下一步,必须调用遍历器对象的next
方法使得指针移向下一个状态。也就是说每次调用next
方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield
表达式(或return
语句)
function* gen() {
const str1 = yield "hello"
// str1 = 222
const str2 = yield "world"
// str2 = 333
return str2
}
const iter = gen()
console.log(iter.next())
console.log(iter.next(222))
console.log(iter.next(333))
第一次调用,generator
函数开始执行,直到遇到第一个yield
表达式为止。next
方法返回一个对象,它的value
值就是当前yield
表达式的值,done的值为false
第二次调用,generator
从上次yield表达式停下来的地方一直执行到下一个yield
表达式 👆 ……
第三次调用,generator
函数从上次yield
表达式停下来的地方一直执行到return
语句,next返回的value
值就是return
后面表达式的值,done
为true(如果是yield
则为false
)
yield
表达式本身没有返回值(或者说总是返回undefined)。next
方法可以带一个参数,该参数会被当作上一个yield
表达式的返回值