对象解构
移除不想要的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| // 移除 _internal 和 tooBig 这两个属性 let { _internal, tooBig, ...cleanObject } = { _internal: "secret", tooBig: {}, el1: '1', el2: '2', el3: '3' }
console.log(cleanObject) // { el1: '1', el2: '2', el3: '3' }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| let obj = { name: 'peter', gender: 'male', other: { age: '28', height: '180', weight: '160' } }
const { other: { age, ...rest2 }, ...rest1 } = obj const person = { ...rest1, ...rest2, age: Number(age) }
console.log(rest1) // { name: 'peter', gender: 'male' } console.log(rest2) // { height: '180', weight: '160' } console.log(person) // { name: 'peter', gender: 'male', height: '180', weight: '160', age: 28 }
|
在函数参数中使用嵌套对象解构
在这个例子中 engine 是一个嵌套在 car 里面的对象,如果我们只需要 engine 里面的属性 vin 我们可以这样做。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const car = { model: 'bmw 2018', engine: { v6: true, turbo: true, vin: 12345 } }
const modelAndVIN = ({ model, engine: { vin } }) => { console.log(`model: ${model} vin: ${vin}`) }
modelAndVIN(car) // model: bmw 2018 vin: 12345
|
合并对象
扩展运算符…
1 2 3
| let object1 = { a:1, b:2,c:3 } let object2 = { b:30, c:40, d:50 } let merged = { …object1, …object2 } //spread and re-add into merged
|
根据条件添加对象属性
你不再需要根据条件创建两个不同的对象,以使其具有特定属性。扩展操作符将是一个完美的选择
1 2 3 4 5 6 7 8 9 10 11 12 13
| const getUser = (emailIncluded) => { return { name: 'John', surname: 'Doe', ...(emailIncluded ? { email : 'john@doe.com' } : null) } }
const user = getUser(true) console.log(user); // 输出 { name: "John", surname: "Doe", email: "john@doe.com" }
const userWithoutEmail = getUser(false) console.log(userWithoutEmail) // 输出 { name: "John", surname: "Doe" }
|
解构原始数据
你曾经有处理过拥有非常多属性的对象吗?我相信你一定有过。可能最常见的情况是我们有一个用户对象,它包含了所有的数据和细节。这里,我们可以调用新的 ES 解构方法来处理这个大麻烦。让我们看看下面的例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const rawUser = { name: 'John', surname: 'Doe', email: 'john@doe.com', displayName: 'SuperCoolJohn', joined: '2016-05-05', image: 'path-to-the-image', followers: 45 ... }
let user = {}, userDetails = {}; ({ name: user.name, surname: user.surname, ...userDetails } = rawUser);
console.log(user) // 输出 { name: "John", surname: "Doe" } console.log(userDetails) // 输出 { email: "john@doe.com", displayName: "SuperCoolJohn", joined: "2016-05-05", image: "path-to-the-image", followers: 45 }
|
合并对象数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| // 将对象数组合并成一个对象 const cities = [ { name: 'Paris', visited: 'no' }, { name: 'Lyon', visited: 'no' }, { name: 'Marseille', visited: 'yes' }, { name: 'Rome', visited: 'yes' }, { name: 'Milan', visited: 'no' }, { name: 'Palermo', visited: 'yes' }, { name: 'Genoa', visited: 'yes' }, { name: 'Berlin', visited: 'no' }, { name: 'Hamburg', visited: 'yes' }, { name: 'New York', visited: 'yes' } ]
const result = cities.reduce((accumulator, item) => { return { ...accumulator, [item.name]: item.visited } }, {})
console.log(result) /* 输出 { Berlin: "no" Genoa: "yes" Hamburg: "yes" Lyon: "no" Marseille: "yes" Milan: "no" New York: "yes" Palermo: "yes" Paris: "no" Rome: "yes" } */
|
数组映射
不使用 Array.map
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const cities = [ { name: 'Paris', visited: 'no' }, { name: 'Lyon', visited: 'no' }, { name: 'Marseille', visited: 'yes' }, { name: 'Rome', visited: 'yes' }, { name: 'Milan', visited: 'no' }, { name: 'Palermo', visited: 'yes' }, { name: 'Genoa', visited: 'yes' }, { name: 'Berlin', visited: 'no' }, { name: 'Hamburg', visited: 'yes' }, { name: 'New York', visited: 'yes' } ]
const cityNames = Array.from(cities, ({ name}) => name) console.log(cityNames) // 输出 ["Paris", "Lyon", "Marseille", "Rome", "Milan", "Palermo", "Genoa", "Berlin", "Hamburg", "New York"]
|
数组的解构
交换2个值
1 2 3 4
| const [post, comments] = Promise.all([ fetch('/post'), fetch('/comments') ])
|
使用 Array 的方法
可以通过 (…) 扩展运算符将 Set 转换成 Array 这样我们就可以在 Set 使用所有 Array 的方法了。
1 2
| let mySet = newSet([1,2, 3, 4, 5]) const filtered = [...mySet].filter((x) => x > 3) // [4, 5]
|
Set
使用 set 来对数组去重
1 2 3
| let arr = [1, 1, 2, 2, 3, 3] let deduped = [...new Set(arr)] // [1, 2, 3] let deduped = Array.from(new Set(arr))
|
Map
使用对象初始化 Map 实例
1 2 3 4 5
| let obj = { a: 1, b: 1, c: 1 } map = new Map(Object.entries(obj)) console.log(map.get('a')) // 1 console.log(map.get('b')) console.log(map.get('c'))
|
模板字符串
如果这样做的话:
1 2
| const string = `First Second`
|
那么它会创建出像下面的字符串:
有一个简单的方法可以修复这个问题,只需要将第一行置为空,然后添加了右边的翻译好后调用一个 trim() 方法,就可以消除第一个字符前的所有空格:
1 2 3
| const string = ` First Second`.trim()
|
对象方法
Object.is() 确定两个值是不是同一个
扩展运算符
用在字符串上的时候,展开操作符会以字符串中的每一个字符创建一个数组:
1 2
| const hey = 'hey' const arrayized = [...hey] // ['h', 'e', 'y']
|
不定参数
在之前的语法规范中,你只能通过fn.apply(null, arr)的方式来实现,但是这种方式不是很友好和易读。
1 2
| const arr = [1, 3, 0, -1, 20, 100] Math.max.apply(null, arr) // 100
|
1 2 3 4 5
| const array = [1, 2, 3, 4, 5] function fn() { console.log(arguments) } fn.apply(null, array) // Arguments(5) [0: 1, 1: 2, 2: 3, 3: 4, 4: 5]
|
现在,剩余参数(rest element)在和数组解构(array destructuring)搭配使用来实现。
1 2 3 4 5 6
| const array = [1, 2, 3, 4, 5] const fn = (foo, bar, ...rest) => { console.log(rest) console.log(...arguments) } fn(...array) // [3, 4, 5]
|
箭头函数没有 arguments
1 2 3 4 5
| const array = [1, 2, 3, 4, 5] function fn() { console.log(...arguments) } fn(...array) // 1 2 3 4 5
|
Generator
一个解释generator如何工作的例子:
1 2 3 4 5
| function *calculator(input) { var doubleThat = 2 * (yield (input / 2)) var another = yield (doubleThat) return (input * doubleThat * another) }
|
我们先初始化它:``
1
| const calc = calculator(10)
|
然后我们在generator中开始进行iterator迭代:
1 2 3 4 5 6 7
| calc.next()
// { done: false, value: 5 }
|
具体过程如下:代码运行了函数,并把input=10传入到生成器构造函数中,该函数一直运行直到抵达 yield,并返回 yield 输出的内容: input / 2 = 5,因此,我们得到的值为5,并告知迭代器还没有 done (函数只是暂停了)。
在第二个迭代处,我们输入7:
1 2 3 4
| { done: false value: 14 }
|
7被作为 doubleThat 的值,注意:你可能会把input/2作为输入参数,但这只是第一次迭代的返回值。现在我们忽略它,使用新的输入值7,并将其乘以2。
然后,我们得到第二个 yield 的值,它返回 doubleThat,因此返回值为14。
之后,也是最后一个迭代器,我们输入100:
1 2 3 4 5 6 7
| calc.next(100)
// { done: true value: 14000 }
|
当迭代器完成时(没有更多的 yield 关键字),我们返回 input doubleThat another,这相当于10 * 14 * 100。