From 8c8be74712a9e0d1a5dbcc855fe3e574b9fd4e6b Mon Sep 17 00:00:00 2001 From: ruanyf Date: Sun, 2 Jul 2017 09:37:23 +0800 Subject: [PATCH] docs(array): move spread operator into array chapter --- docs/array.md | 303 ++++++++++++++++++++++++++++++++++++++++++++++- docs/async.md | 8 +- docs/function.md | 277 ------------------------------------------- docs/iterator.md | 4 +- docs/object.md | 28 ++++- sidebar.md | 2 +- 6 files changed, 327 insertions(+), 295 deletions(-) diff --git a/docs/array.md b/docs/array.md index c5e8652..19ab71f 100644 --- a/docs/array.md +++ b/docs/array.md @@ -1,5 +1,298 @@ # 数组的扩展 +## 扩展运算符 + +### 含义 + +扩展运算符(spread)是三个点(`...`)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。 + +```javascript +console.log(...[1, 2, 3]) +// 1 2 3 + +console.log(1, ...[2, 3, 4], 5) +// 1 2 3 4 5 + +[...document.querySelectorAll('div')] +// [
,
,
] +``` + +该运算符主要用于函数调用。 + +```javascript +function push(array, ...items) { + array.push(...items); +} + +function add(x, y) { + return x + y; +} + +var numbers = [4, 38]; +add(...numbers) // 42 +``` + +上面代码中,`array.push(...items)`和`add(...numbers)`这两行,都是函数的调用,它们的都使用了扩展运算符。该运算符将一个数组,变为参数序列。 + +扩展运算符与正常的函数参数可以结合使用,非常灵活。 + +```javascript +function f(v, w, x, y, z) { } +var args = [0, 1]; +f(-1, ...args, 2, ...[3]); +``` + +扩展运算符后面还可以放置表达式。 + +```javascript +const arr = [ + ...(x > 0 ? ['a'] : []), + 'b', +]; +``` + +如果扩展运算符后面是一个空数组,则不产生任何效果。 + +```javascript +[...[], 1] +// [1] +``` + +### 替代数组的 apply 方法 + +由于扩展运算符可以展开数组,所以不再需要`apply`方法,将数组转为函数的参数了。 + +```javascript +// ES5 的写法 +function f(x, y, z) { + // ... +} +var args = [0, 1, 2]; +f.apply(null, args); + +// ES6的写法 +function f(x, y, z) { + // ... +} +var args = [0, 1, 2]; +f(...args); +``` + +下面是扩展运算符取代`apply`方法的一个实际的例子,应用`Math.max`方法,简化求出一个数组最大元素的写法。 + +```javascript +// ES5 的写法 +Math.max.apply(null, [14, 3, 77]) + +// ES6 的写法 +Math.max(...[14, 3, 77]) + +// 等同于 +Math.max(14, 3, 77); +``` + +上面代码中,由于 JavaScript 不提供求数组最大元素的函数,所以只能套用`Math.max`函数,将数组转为一个参数序列,然后求最大值。有了扩展运算符以后,就可以直接用`Math.max`了。 + +另一个例子是通过`push`函数,将一个数组添加到另一个数组的尾部。 + +```javascript +// ES5的 写法 +var arr1 = [0, 1, 2]; +var arr2 = [3, 4, 5]; +Array.prototype.push.apply(arr1, arr2); + +// ES6 的写法 +var arr1 = [0, 1, 2]; +var arr2 = [3, 4, 5]; +arr1.push(...arr2); +``` + +上面代码的 ES5 写法中,`push`方法的参数不能是数组,所以只好通过`apply`方法变通使用`push`方法。有了扩展运算符,就可以直接将数组传入`push`方法。 + +下面是另外一个例子。 + +```javascript +// ES5 +new (Date.bind.apply(Date, [null, 2015, 1, 1])) +// ES6 +new Date(...[2015, 1, 1]); +``` + +### 扩展运算符的应用 + +**(1)合并数组** + +扩展运算符提供了数组合并的新写法。 + +```javascript +// ES5 +[1, 2].concat(more) +// ES6 +[1, 2, ...more] + +var arr1 = ['a', 'b']; +var arr2 = ['c']; +var arr3 = ['d', 'e']; + +// ES5的合并数组 +arr1.concat(arr2, arr3); +// [ 'a', 'b', 'c', 'd', 'e' ] + +// ES6的合并数组 +[...arr1, ...arr2, ...arr3] +// [ 'a', 'b', 'c', 'd', 'e' ] +``` + +**(2)与解构赋值结合** + +扩展运算符可以与解构赋值结合起来,用于生成数组。 + +```javascript +// ES5 +a = list[0], rest = list.slice(1) +// ES6 +[a, ...rest] = list +``` + +下面是另外一些例子。 + +```javascript +const [first, ...rest] = [1, 2, 3, 4, 5]; +first // 1 +rest // [2, 3, 4, 5] + +const [first, ...rest] = []; +first // undefined +rest // [] + +const [first, ...rest] = ["foo"]; +first // "foo" +rest // [] +``` + +如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。 + +```javascript +const [...butLast, last] = [1, 2, 3, 4, 5]; +// 报错 + +const [first, ...middle, last] = [1, 2, 3, 4, 5]; +// 报错 +``` + +**(3)函数的返回值** + +JavaScript 的函数只能返回一个值,如果需要返回多个值,只能返回数组或对象。扩展运算符提供了解决这个问题的一种变通方法。 + +```javascript +var dateFields = readDateFields(database); +var d = new Date(...dateFields); +``` + +上面代码从数据库取出一行数据,通过扩展运算符,直接将其传入构造函数`Date`。 + +**(4)字符串** + +扩展运算符还可以将字符串转为真正的数组。 + +```javascript +[...'hello'] +// [ "h", "e", "l", "l", "o" ] +``` + +上面的写法,有一个重要的好处,那就是能够正确识别32位的Unicode字符。 + +```javascript +'x\uD83D\uDE80y'.length // 4 +[...'x\uD83D\uDE80y'].length // 3 +``` + +上面代码的第一种写法,JavaScript会将32位Unicode字符,识别为2个字符,采用扩展运算符就没有这个问题。因此,正确返回字符串长度的函数,可以像下面这样写。 + +```javascript +function length(str) { + return [...str].length; +} + +length('x\uD83D\uDE80y') // 3 +``` + +凡是涉及到操作32位 Unicode 字符的函数,都有这个问题。因此,最好都用扩展运算符改写。 + +```javascript +let str = 'x\uD83D\uDE80y'; + +str.split('').reverse().join('') +// 'y\uDE80\uD83Dx' + +[...str].reverse().join('') +// 'y\uD83D\uDE80x' +``` + +上面代码中,如果不用扩展运算符,字符串的`reverse`操作就不正确。 + +**(5)实现了 Iterator 接口的对象** + +任何 Iterator 接口的对象(参阅 Iterator 一章),都可以用扩展运算符转为真正的数组。 + +```javascript +var nodeList = document.querySelectorAll('div'); +var array = [...nodeList]; +``` + +上面代码中,`querySelectorAll`方法返回的是一个`nodeList`对象。它不是数组,而是一个类似数组的对象。这时,扩展运算符可以将其转为真正的数组,原因就在于`NodeList`对象实现了 Iterator 。 + +对于那些没有部署 Iterator 接口的类似数组的对象,扩展运算符就无法将其转为真正的数组。 + +```javascript +let arrayLike = { + '0': 'a', + '1': 'b', + '2': 'c', + length: 3 +}; + +// TypeError: Cannot spread non-iterable object. +let arr = [...arrayLike]; +``` + +上面代码中,`arrayLike`是一个类似数组的对象,但是没有部署 Iterator 接口,扩展运算符就会报错。这时,可以改为使用`Array.from`方法将`arrayLike`转为真正的数组。 + +**(6)Map 和 Set 结构,Generator 函数** + +扩展运算符内部调用的是数据结构的 Iterator 接口,因此只要具有 Iterator 接口的对象,都可以使用扩展运算符,比如 Map 结构。 + +```javascript +let map = new Map([ + [1, 'one'], + [2, 'two'], + [3, 'three'], +]); + +let arr = [...map.keys()]; // [1, 2, 3] +``` + +Generator 函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符。 + +```javascript +var go = function*(){ + yield 1; + yield 2; + yield 3; +}; + +[...go()] // [1, 2, 3] +``` + +上面代码中,变量`go`是一个 Generator 函数,执行后返回的是一个遍历器对象,对这个遍历器对象执行扩展运算符,就会将内部遍历得到的值,转为一个数组。 + +如果对没有 Iterator 接口的对象,使用扩展运算符,将会报错。 + +```javascript +var obj = {a: 1, b: 2}; +let arr = [...obj]; // TypeError: Cannot spread non-iterable object +``` + ## Array.from() `Array.from`方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)。 @@ -185,7 +478,7 @@ function ArrayOf(){ } ``` -## 数组实例的copyWithin() +## 数组实例的 copyWithin() 数组实例的`copyWithin`方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。 @@ -228,13 +521,13 @@ var i32a = new Int32Array([1, 2, 3, 4, 5]); i32a.copyWithin(0, 2); // Int32Array [3, 4, 5, 4, 5] -// 对于没有部署TypedArray的copyWithin方法的平台 +// 对于没有部署 TypedArray 的 copyWithin 方法的平台 // 需要采用下面的写法 [].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4); // Int32Array [4, 2, 3, 4, 5] ``` -## 数组实例的find()和findIndex() +## 数组实例的 find() 和 findIndex() 数组实例的`find`方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为`true`的成员,然后返回该成员。如果没有符合条件的成员,则返回`undefined`。 @@ -298,9 +591,9 @@ new Array(3).fill(7) 上面代码表示,`fill`方法从1号位开始,向原数组填充7,到2号位之前结束。 -## 数组实例的entries(),keys()和values() +## 数组实例的 entries(),keys() 和 values() -ES6提供三个新的方法——`entries()`,`keys()`和`values()`——用于遍历数组。它们都返回一个遍历器对象(详见《Iterator》一章),可以用`for...of`循环进行遍历,唯一的区别是`keys()`是对键名的遍历、`values()`是对键值的遍历,`entries()`是对键值对的遍历。 +ES6 提供三个新的方法——`entries()`,`keys()`和`values()`——用于遍历数组。它们都返回一个遍历器对象(详见《Iterator》一章),可以用`for...of`循环进行遍历,唯一的区别是`keys()`是对键名的遍历、`values()`是对键值的遍历,`entries()`是对键值对的遍历。 ```javascript for (let index of ['a', 'b'].keys()) { diff --git a/docs/async.md b/docs/async.md index 512b89f..2510899 100644 --- a/docs/async.md +++ b/docs/async.md @@ -775,7 +775,7 @@ async function () { // b ``` -### 异步Generator函数 +### 异步 Generator 函数 就像 Generator 函数返回一个同步遍历器对象一样,异步 Generator 函数的作用,是返回一个异步遍历器对象。 @@ -795,9 +795,9 @@ async function* readLines(path) { } ``` -上面代码中,异步操作前面使用`await`关键字标明,即`await`后面的操作,应该返回Promise对象。凡是使用`yield`关键字的地方,就是`next`方法的停下来的地方,它后面的表达式的值(即`await file.readLine()`的值),会作为`next()`返回对象的`value`属性,这一点是于同步Generator函数一致的。 +上面代码中,异步操作前面使用`await`关键字标明,即`await`后面的操作,应该返回 Promise 对象。凡是使用`yield`关键字的地方,就是`next`方法的停下来的地方,它后面的表达式的值(即`await file.readLine()`的值),会作为`next()`返回对象的`value`属性,这一点是于同步 Generator 函数一致的。 -可以像下面这样,使用上面代码定义的异步Generator函数。 +可以像下面这样,使用上面代码定义的异步 Generator 函数。 ```javascript for await (const line of readLines(filePath)) { @@ -815,7 +815,7 @@ async function* prefixLines(asyncIterable) { } ``` -`yield`命令依然是立刻返回的,但是返回的是一个Promise对象。 +`yield`命令依然是立刻返回的,但是返回的是一个 Promise 对象。 ```javascript async function* asyncGenerator() { diff --git a/docs/function.md b/docs/function.md index 5b2e877..8779572 100644 --- a/docs/function.md +++ b/docs/function.md @@ -444,283 +444,6 @@ function f(a, ...b, c) { (function(a, ...b) {}).length // 1 ``` -## 扩展运算符 - -### 含义 - -扩展运算符(spread)是三个点(`...`)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。 - -```javascript -console.log(...[1, 2, 3]) -// 1 2 3 - -console.log(1, ...[2, 3, 4], 5) -// 1 2 3 4 5 - -[...document.querySelectorAll('div')] -// [
,
,
] -``` - -该运算符主要用于函数调用。 - -```javascript -function push(array, ...items) { - array.push(...items); -} - -function add(x, y) { - return x + y; -} - -var numbers = [4, 38]; -add(...numbers) // 42 -``` - -上面代码中,`array.push(...items)`和`add(...numbers)`这两行,都是函数的调用,它们的都使用了扩展运算符。该运算符将一个数组,变为参数序列。 - -扩展运算符与正常的函数参数可以结合使用,非常灵活。 - -```javascript -function f(v, w, x, y, z) { } -var args = [0, 1]; -f(-1, ...args, 2, ...[3]); -``` - -### 替代数组的apply方法 - -由于扩展运算符可以展开数组,所以不再需要`apply`方法,将数组转为函数的参数了。 - -```javascript -// ES5的写法 -function f(x, y, z) { - // ... -} -var args = [0, 1, 2]; -f.apply(null, args); - -// ES6的写法 -function f(x, y, z) { - // ... -} -var args = [0, 1, 2]; -f(...args); -``` - -下面是扩展运算符取代`apply`方法的一个实际的例子,应用`Math.max`方法,简化求出一个数组最大元素的写法。 - -```javascript -// ES5的写法 -Math.max.apply(null, [14, 3, 77]) - -// ES6的写法 -Math.max(...[14, 3, 77]) - -// 等同于 -Math.max(14, 3, 77); -``` - -上面代码表示,由于JavaScript不提供求数组最大元素的函数,所以只能套用`Math.max`函数,将数组转为一个参数序列,然后求最大值。有了扩展运算符以后,就可以直接用`Math.max`了。 - -另一个例子是通过`push`函数,将一个数组添加到另一个数组的尾部。 - -```javascript -// ES5的写法 -var arr1 = [0, 1, 2]; -var arr2 = [3, 4, 5]; -Array.prototype.push.apply(arr1, arr2); - -// ES6的写法 -var arr1 = [0, 1, 2]; -var arr2 = [3, 4, 5]; -arr1.push(...arr2); -``` - -上面代码的ES5写法中,`push`方法的参数不能是数组,所以只好通过`apply`方法变通使用`push`方法。有了扩展运算符,就可以直接将数组传入`push`方法。 - -下面是另外一个例子。 - -```javascript -// ES5 -new (Date.bind.apply(Date, [null, 2015, 1, 1])) -// ES6 -new Date(...[2015, 1, 1]); -``` - -### 扩展运算符的应用 - -**(1)合并数组** - -扩展运算符提供了数组合并的新写法。 - -```javascript -// ES5 -[1, 2].concat(more) -// ES6 -[1, 2, ...more] - -var arr1 = ['a', 'b']; -var arr2 = ['c']; -var arr3 = ['d', 'e']; - -// ES5的合并数组 -arr1.concat(arr2, arr3); -// [ 'a', 'b', 'c', 'd', 'e' ] - -// ES6的合并数组 -[...arr1, ...arr2, ...arr3] -// [ 'a', 'b', 'c', 'd', 'e' ] -``` - -**(2)与解构赋值结合** - -扩展运算符可以与解构赋值结合起来,用于生成数组。 - -```javascript -// ES5 -a = list[0], rest = list.slice(1) -// ES6 -[a, ...rest] = list -``` - -下面是另外一些例子。 - -```javascript -const [first, ...rest] = [1, 2, 3, 4, 5]; -first // 1 -rest // [2, 3, 4, 5] - -const [first, ...rest] = []; -first // undefined -rest // [] - -const [first, ...rest] = ["foo"]; -first // "foo" -rest // [] -``` - -如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。 - -```javascript -const [...butLast, last] = [1, 2, 3, 4, 5]; -// 报错 - -const [first, ...middle, last] = [1, 2, 3, 4, 5]; -// 报错 -``` - -**(3)函数的返回值** - -JavaScript的函数只能返回一个值,如果需要返回多个值,只能返回数组或对象。扩展运算符提供了解决这个问题的一种变通方法。 - -```javascript -var dateFields = readDateFields(database); -var d = new Date(...dateFields); -``` - -上面代码从数据库取出一行数据,通过扩展运算符,直接将其传入构造函数`Date`。 - -**(4)字符串** - -扩展运算符还可以将字符串转为真正的数组。 - -```javascript -[...'hello'] -// [ "h", "e", "l", "l", "o" ] -``` - -上面的写法,有一个重要的好处,那就是能够正确识别32位的Unicode字符。 - -```javascript -'x\uD83D\uDE80y'.length // 4 -[...'x\uD83D\uDE80y'].length // 3 -``` - -上面代码的第一种写法,JavaScript会将32位Unicode字符,识别为2个字符,采用扩展运算符就没有这个问题。因此,正确返回字符串长度的函数,可以像下面这样写。 - -```javascript -function length(str) { - return [...str].length; -} - -length('x\uD83D\uDE80y') // 3 -``` - -凡是涉及到操作32位Unicode字符的函数,都有这个问题。因此,最好都用扩展运算符改写。 - -```javascript -let str = 'x\uD83D\uDE80y'; - -str.split('').reverse().join('') -// 'y\uDE80\uD83Dx' - -[...str].reverse().join('') -// 'y\uD83D\uDE80x' -``` - -上面代码中,如果不用扩展运算符,字符串的`reverse`操作就不正确。 - -**(5)实现了Iterator接口的对象** - -任何Iterator接口的对象,都可以用扩展运算符转为真正的数组。 - -```javascript -var nodeList = document.querySelectorAll('div'); -var array = [...nodeList]; -``` - -上面代码中,`querySelectorAll`方法返回的是一个`nodeList`对象。它不是数组,而是一个类似数组的对象。这时,扩展运算符可以将其转为真正的数组,原因就在于`NodeList`对象实现了Iterator接口。 - -对于那些没有部署Iterator接口的类似数组的对象,扩展运算符就无法将其转为真正的数组。 - -```javascript -let arrayLike = { - '0': 'a', - '1': 'b', - '2': 'c', - length: 3 -}; - -// TypeError: Cannot spread non-iterable object. -let arr = [...arrayLike]; -``` - -上面代码中,`arrayLike`是一个类似数组的对象,但是没有部署Iterator接口,扩展运算符就会报错。这时,可以改为使用`Array.from`方法将`arrayLike`转为真正的数组。 - -**(6)Map和Set结构,Generator函数** - -扩展运算符内部调用的是数据结构的Iterator接口,因此只要具有Iterator接口的对象,都可以使用扩展运算符,比如Map结构。 - -```javascript -let map = new Map([ - [1, 'one'], - [2, 'two'], - [3, 'three'], -]); - -let arr = [...map.keys()]; // [1, 2, 3] -``` - -Generator函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符。 - -```javascript -var go = function*(){ - yield 1; - yield 2; - yield 3; -}; - -[...go()] // [1, 2, 3] -``` - -上面代码中,变量`go`是一个Generator函数,执行后返回的是一个遍历器对象,对这个遍历器对象执行扩展运算符,就会将内部遍历得到的值,转为一个数组。 - -如果对没有`iterator`接口的对象,使用扩展运算符,将会报错。 - -```javascript -var obj = {a: 1, b: 2}; -let arr = [...obj]; // TypeError: Cannot spread non-iterable object -``` - ## 严格模式 从 ES5 开始,函数内部可以设定为严格模式。 diff --git a/docs/iterator.md b/docs/iterator.md index 46e2ca7..746032f 100644 --- a/docs/iterator.md +++ b/docs/iterator.md @@ -544,7 +544,7 @@ arr.forEach(function (element, index) { }); ``` -JavaScript原有的`for...in`循环,只能获得对象的键名,不能直接获取键值。ES6提供`for...of`循环,允许遍历获得键值。 +JavaScript 原有的`for...in`循环,只能获得对象的键名,不能直接获取键值。ES6 提供`for...of`循环,允许遍历获得键值。 ```javascript var arr = ['a', 'b', 'c', 'd']; @@ -577,7 +577,7 @@ for (let i of arr) { 上面代码中,`for...of`循环不会返回数组`arr`的`foo`属性。 -### Set和Map结构 +### Set 和 Map 结构 Set 和 Map 结构也原生具有 Iterator 接口,可以直接使用`for...of`循环。 diff --git a/docs/object.md b/docs/object.md index 4b490cc..de1798c 100644 --- a/docs/object.md +++ b/docs/object.md @@ -432,7 +432,7 @@ Object.assign({b: 'c'}, 上面代码中,`Object.assign`要拷贝的对象只有一个不可枚举属性`invisible`,这个属性并没有被拷贝进去。 -属性名为Symbol值的属性,也会被`Object.assign`拷贝。 +属性名为 Symbol 值的属性,也会被`Object.assign`拷贝。 ```javascript Object.assign({ a: 'b' }, { [Symbol('c')]: 'd' }) @@ -601,13 +601,13 @@ Object.getOwnPropertyDescriptor(obj, 'foo') 描述对象的`enumerable`属性,称为”可枚举性“,如果该属性为`false`,就表示某些操作会忽略当前属性。 -ES5有三个操作会忽略`enumerable`为`false`的属性。 +ES5 有三个操作会忽略`enumerable`为`false`的属性。 - `for...in`循环:只遍历对象自身的和继承的可枚举的属性 - `Object.keys()`:返回对象自身的所有可枚举的属性的键名 - `JSON.stringify()`:只串行化对象自身的可枚举的属性 -ES6新增了一个操作`Object.assign()`,会忽略`enumerable`为`false`的属性,只拷贝对象自身的可枚举的属性。 +ES6 新增了一个操作`Object.assign()`,会忽略`enumerable`为`false`的属性,只拷贝对象自身的可枚举的属性。 这四个操作之中,只有`for...in`会返回继承的属性。实际上,引入`enumerable`的最初目的,就是让某些属性可以规避掉`for...in`操作。比如,对象原型的`toString`方法,以及数组的`length`属性,就通过这种手段,不会被`for...in`遍历到。 @@ -1123,7 +1123,7 @@ let aWithOverrides = Object.assign({}, a, { x: 1, y: 2 }); 上面代码中,`a`对象的`x`属性和`y`属性,拷贝到新对象后会被覆盖掉。 -这用来修改现有对象部分的部分属性就很方便了。 +这用来修改现有对象部分的属性就很方便了。 ```javascript let newVersion = { @@ -1134,6 +1134,22 @@ let newVersion = { 上面代码中,`newVersion`对象自定义了`name`属性,其他属性全部复制自`previousVersion`对象。 +与数组的扩展运算符一样,对象的扩展运算符后面可以跟表达式。 + +```javascript +const obj = { + ...(x > 1 ? {a: 1} : {}), + b: 2, +}; +``` + +如果扩展运算符后面是一个空对象,则没有任何效果。 + +```javascript +{...{}, a: 1} +// { a: 1 } +``` + 如果把自定义属性放在扩展运算符前面,就变成了设置新对象的默认属性值。 ```javascript @@ -1147,7 +1163,7 @@ let aWithDefaults = Object.assign({ x: 1, y: 2 }, a); 扩展运算符的参数对象之中,如果有取值函数`get`,这个函数是会执行的。 ```javascript -// 并不会抛出错误,因为x属性只是被定义,但没执行 +// 并不会抛出错误,因为 x 属性只是被定义,但没执行 let aWithXGetter = { ...a, get x() { @@ -1155,7 +1171,7 @@ let aWithXGetter = { } }; -// 会抛出错误,因为x属性被执行了 +// 会抛出错误,因为 x 属性被执行了 let runtimeError = { ...a, ...{ diff --git a/sidebar.md b/sidebar.md index 8b0d64d..55a86c1 100644 --- a/sidebar.md +++ b/sidebar.md @@ -12,8 +12,8 @@ 1. [字符串的扩展](#docs/string) 1. [正则的扩展](#docs/regex) 1. [数值的扩展](#docs/number) -1. [数组的扩展](#docs/array) 1. [函数的扩展](#docs/function) +1. [数组的扩展](#docs/array) 1. [对象的扩展](#docs/object) 1. [Symbol](#docs/symbol) 1. [Set 和 Map 数据结构](#docs/set-map)