<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 1.函數的rest參數 ES6 引入 rest 參數(形式為`...變量名`),用于獲取函數的多余參數,這樣就不需要使用`arguments`對象了。rest 參數搭配的變量是一個數組,該變量將多余的參數放入數組中。 ~~~javascript // arguments變量的寫法 function sortNumbers() { return Array.prototype.slice.call(arguments).sort(); } // rest參數的寫法 const sortNumbers = (...numbers) => numbers.sort(); ~~~ `arguments`對象不是數組,而是一個類似數組的對象。所以為了使用數組的方法,必須使用`Array.prototype.slice.call`先將其轉為數組。rest 參數就不存在這個問題,它就是一個真正的數組,數組特有的方法都可以使用。下面是一個利用 rest 參數改寫數組`push`方法的例子。 ~~~javascript function push(array, ...items) { items.forEach(function(item) { array.push(item); console.log(item); }); } var a = []; push(a, 1, 2, 3) ~~~ >注意,rest 參數之后不能再有其他參數(即只能是最后一個參數),否則會報錯。 ~~~javascript // 報錯 function f(a, ...b, c) { // ... } ~~~ ### 2.數組的擴展運算符 擴展運算符(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')] // [<div>, <div>, <div>] ~~~ 該運算符主要用于函數調用。 ~~~javascript function push(array, ...items) { array.push(...items); } function add(x, y) { return x + y; } const numbers = [4, 38]; add(...numbers) // 42 ~~~ 擴展運算符與正常的函數參數可以結合使用,非常靈活。 ~~~javascript function f(v, w, x, y, z) { } const args = [0, 1]; f(-1, ...args, 2, ...[3]); ~~~ 擴展運算符后面還可以放置表達式。 ~~~javascript const arr = [ ...(x > 0 ? ['a'] : []), 'b', ]; ~~~ 注意,擴展運算符如果放在括號中,JavaScript 引擎就會認為這是函數調用。如果這時不是函數調用,就會報錯。 ~~~javascript (...[1, 2]) // Uncaught SyntaxError: Unexpected number console.log((...[1, 2])) // Uncaught SyntaxError: Unexpected number console.log(...[1, 2]) // 1 2 ~~~ #### 替代函數的 apply 方法 ~~~javascript // ES5 的寫法 function f(x, y, z) { // ... } var args = [0, 1, 2]; f.apply(null, args); // ES6的寫法 function f(x, y, z) { // ... } let 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 的寫法 let arr1 = [0, 1, 2]; let 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)復制數組** ES5 只能用變通方法來復制數組。 ~~~javascript const a1 = [1, 2]; const a2 = a1.concat(); a2[0] = 2; a1 // [1, 2] ~~~ 上面代碼中,`a1`會返回原數組的克隆,再修改`a2`就不會對`a1`產生影響。 擴展運算符提供了復制數組的簡便寫法。 ~~~javascript const a1 = [1, 2]; // 寫法一 const a2 = [...a1]; // 寫法二 const [...a2] = a1; ~~~ 上面的兩種寫法,`a2`都是`a1`的克隆。 **(2)合并數組** 擴展運算符提供了數組合并的新寫法。 ~~~javascript const arr1 = ['a', 'b']; const arr2 = ['c']; const arr3 = ['d', 'e']; // ES5 的合并數組 arr1.concat(arr2, arr3); // [ 'a', 'b', 'c', 'd', 'e' ] // ES6 的合并數組 [...arr1, ...arr2, ...arr3] // [ 'a', 'b', 'c', 'd', 'e' ] ~~~ 不過,這兩種方法都是淺拷貝,使用的時候需要注意。 ~~~javascript const a1 = [{ foo: 1 }]; const a2 = [{ bar: 2 }]; const a3 = a1.concat(a2); const a4 = [...a1, ...a2]; a3[0] === a1[0] // true a4[0] === a1[0] // true ~~~ 上面代碼中,`a3`和`a4`是用兩種不同方法合并而成的新數組,但是它們的成員都是對原數組成員的引用,這就是淺拷貝。如果修改了原數組的成員,會同步反映到新數組。 **(3)與解構賦值結合** 擴展運算符可以與解構賦值結合起來,用于生成數組。 ~~~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.對象的擴展運算符 **(1)解構賦值** 對象的解構賦值用于從一個對象取值,相當于將目標對象自身的所有可遍歷的(enumerable)、但尚未被讀取的屬性,分配到指定的對象上面。所有的鍵和它們的值,都會拷貝到新對象上面。 ~~~javascript let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; x // 1 y // 2 z // { a: 3, b: 4 } ~~~ 上面代碼中,變量`z`是解構賦值所在的對象。它獲取等號右邊的所有尚未讀取的鍵(`a`和`b`),將它們連同值一起拷貝過來。 由于解構賦值要求等號右邊是一個對象,所以如果等號右邊是`undefined`或`null`,就會報錯,因為它們無法轉為對象。 ~~~javascript let { x, y, ...z } = null; // 運行時錯誤 let { x, y, ...z } = undefined; // 運行時錯誤 ~~~ 解構賦值必須是最后一個參數,否則會報錯。 ~~~javascript let { ...x, y, z } = someObject; // 句法錯誤 let { x, ...y, ...z } = someObject; // 句法錯誤 ~~~ 上面代碼中,解構賦值不是最后一個參數,所以會報錯。 注意,解構賦值的拷貝是淺拷貝,即如果一個鍵的值是復合類型的值(數組、對象、函數)、那么解構賦值拷貝的是這個值的引用,而不是這個值的副本。 ~~~javascript let obj = { a: { b: 1 } }; let { ...x } = obj; obj.a.b = 2; x.a.b // 2 ~~~ 上面代碼中,`x`是解構賦值所在的對象,拷貝了對象`obj`的`a`屬性。`a`屬性引用了一個對象,修改這個對象的值,會影響到解構賦值對它的引用。 另外,擴展運算符的解構賦值,不能復制繼承自原型對象的屬性。 ~~~javascript let o1 = { a: 1 }; let o2 = { b: 2 }; o2.__proto__ = o1; let { ...o3 } = o2; o3 // { b: 2 } o3.a // undefined ~~~ 上面代碼中,對象`o3`復制了`o2`,但是只復制了`o2`自身的屬性,沒有復制它的原型對象`o1`的屬性。 下面是另一個例子。 ~~~javascript const o = Object.create({ x: 1, y: 2 }); o.z = 3; let { x, ...newObj } = o; let { y, z } = newObj; x // 1 y // undefined z // 3 ~~~ 上面代碼中,變量`x`是單純的解構賦值,所以可以讀取對象`o`繼承的屬性;變量`y`和`z`是擴展運算符的解構賦值,只能讀取對象`o`自身的屬性,所以變量`z`可以賦值成功,變量`y`取不到值。ES6 規定,變量聲明語句之中,如果使用解構賦值,擴展運算符后面必須是一個變量名,而不能是一個解構賦值表達式,所以上面代碼引入了中間變量`newObj`,如果寫成下面這樣會報錯。 ~~~javascript let { x, ...{ y, z } } = o; // SyntaxError: ... must be followed by an identifier in declaration contexts ~~~ 解構賦值的一個用處,是擴展某個函數的參數,引入其他操作。 ~~~javascript function baseFunction({ a, b }) { // ... } function wrapperFunction({ x, y, ...restConfig }) { // 使用 x 和 y 參數進行操作 // 其余參數傳給原始函數 return baseFunction(restConfig); } ~~~ 上面代碼中,原始函數`baseFunction`接受`a`和`b`作為參數,函數`wrapperFunction`在`baseFunction`的基礎上進行了擴展,能夠接受多余的參數,并且保留原始函數的行為。 **(2)擴展運算符** 對象的擴展運算符(`...`)用于取出參數對象的所有可遍歷屬性,拷貝到當前對象之中。 ~~~javascript let z = { a: 3, b: 4 }; let n = { ...z }; n // { a: 3, b: 4 } ~~~ 由于數組是特殊的對象,所以對象的擴展運算符也可以用于數組。 ~~~javascript let foo = { ...['a', 'b', 'c'] }; foo // {0: "a", 1: "b", 2: "c"} ~~~ 如果擴展運算符后面是一個空對象,則沒有任何效果。 ~~~javascript {...{}, a: 1} // { a: 1 } ~~~ 如果擴展運算符后面不是對象,則會自動將其轉為對象。 ~~~javascript // 等同于 {...Object(1)} {...1} // {} ~~~ 上面代碼中,擴展運算符后面是整數`1`,會自動轉為數值的包裝對象`Number{1}`。由于該對象沒有自身屬性,所以返回一個空對象。 下面的例子都是類似的道理。 ~~~javascript // 等同于 {...Object(true)} {...true} // {} // 等同于 {...Object(undefined)} {...undefined} // {} // 等同于 {...Object(null)} {...null} // {} ~~~ 但是,如果擴展運算符后面是字符串,它會自動轉成一個類似數組的對象,因此返回的不是空對象。 ~~~javascript {...'hello'} // {0: "h", 1: "e", 2: "l", 3: "l", 4: "o"} ~~~ 對象的擴展運算符等同于使用`Object.assign()`方法。 ~~~javascript let aClone = { ...a }; // 等同于 let aClone = Object.assign({}, a); ~~~ 擴展運算符可以用于合并兩個對象。 ~~~javascript let ab = { ...a, ...b }; // 等同于 let ab = Object.assign({}, a, b); ~~~ 如果用戶自定義的屬性,放在擴展運算符后面,則擴展運算符內部的同名屬性會被覆蓋掉。 ~~~javascript let aWithOverrides = { ...a, x: 1, y: 2 }; // 等同于 let aWithOverrides = { ...a, ...{ x: 1, y: 2 } }; // 等同于 let x = 1, y = 2, aWithOverrides = { ...a, x, y }; // 等同于 let aWithOverrides = Object.assign({}, a, { x: 1, y: 2 }); ~~~ 上面代碼中,`a`對象的`x`屬性和`y`屬性,拷貝到新對象后會被覆蓋掉。 這用來修改現有對象部分的屬性就很方便了。 ~~~javascript let newVersion = { ...previousVersion, name: 'New Name' // Override the name property }; ~~~ 上面代碼中,`newVersion`對象自定義了`name`屬性,其他屬性全部復制自`previousVersion`對象。 如果把自定義屬性放在擴展運算符前面,就變成了設置新對象的默認屬性值。 ~~~javascript let aWithDefaults = { x: 1, y: 2, ...a }; // 等同于 let aWithDefaults = Object.assign({}, { x: 1, y: 2 }, a); // 等同于 let aWithDefaults = Object.assign({ x: 1, y: 2 }, a); ~~~ 與數組的擴展運算符一樣,對象的擴展運算符后面可以跟表達式。 ~~~javascript const obj = { ...(x > 1 ? {a: 1} : {}), b: 2, }; ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看