JavaScript >> Javascript 文檔 >  >> JavaScript

JavaScript 中的擴展運算符

簡介

在本教程中,我們將探索 JavaScript 的 ES6 規範的強大功能之一——Spread Operator。儘管語法很簡單,但如果您沒有正確理解它,有時實現會令人困惑。在本教程中,我們將揭開這三個點 ... 的神秘面紗 使用可迭代對像做驚人事情的 JavaScript。

展開運算符的用法

展開算子有不同的用法,每個使用目標解決不同的問題陳述。

擴展數組

我們可以在可迭代對象(如字符串或數組)上使用擴展運算符,它將可迭代對象的內容放入單個元素中。

舉個例子:

let greet = ['Hello', 'World'];
console.log(greet); // Without spread operator
console.log(...greet); // Using spread operator

如果我們運行此代碼,我們將看到以下內容:

['Hello', 'World']
Hello World

您一定已經註意到,在第二種情況下(使用擴展運算符),greet 的內容 列表被擴展並拋出數組。

有時,我們可能覺得需要轉換一個 String 到字符列表中。我們可以在這個用例中使用擴展運算符:

let greetings = "hello";
let chars = [...greetings];
console.log(chars);

如果我們運行這段代碼,我們會收到:

[ 'h', 'e', 'l', 'l', 'o' ]

這些示例可能無法讓您相信此運算符提供的有用性。以這個名字,讓我們來看看一些可以用擴展運算符解決的現實問題。

組合數組

讓我們利用我們現在可以使用擴展運算符擴展數組這一事實。假設我們有來自兩個不同來源的訂閱者列表,我們希望將這兩個來源結合起來並製作一個訂閱者列表:

let blog1Subscribers = ['[email protected]', '[email protected]'];
let blog2Subscribers = ['[email protected]', '[email protected]', '[email protected]'];
let subscribers = [...blog1Subscribers, ...blog2Subscribers];
console.log(subscribers);

如果我們運行上面的代碼,我們將得到一個可迭代的列表。這是因為 ...blog1Subscribers...blog2Subscribers 散開,[] 充當“接收者”,有效地將分散的項目組合成一個項目列表。

注意: 擴展運算符需要接收者將擴展值放入。如果省略receiver,會報錯。

我們還可以在 Array.push() 中使用擴展運算符 將一個數組的內容推送到另一個數組的方法:

let arr1 = ['John', 'Sofia', 'Bob'];
let arr2 = ['Julia', 'Sean', 'Anthony'];
arr1.push(...arr2);
console.log(arr1);

如果我們運行這段代碼,我們將看到以下輸出:

[ 'John', 'Sofia', 'Bob', 'Julia', 'Sean', 'Anthony' ]

複製數組和對象

在 JavaScript 中,每個非原始實體都是一個 Object ,這意味著數組也是對象。您可能知道對像被複製為引用類型:

let arr1 = ['John', 'Sofia', 'Bob'];
let arr2 = arr1;
console.log(arr2);
arr1.push('Sally'); // Change arr1
console.log(arr2);
[ 'John', 'Sofia', 'Bob' ]
[ 'John', 'Sofia', 'Bob', 'Sally' ]

正如預期的那樣,數組中項目的值沒有被複製,只是對它們的引用。我們可以使用展開運算符輕鬆解決這個問題:

let arr1 = ['John', 'Sofia', 'Bob'];
let arr2 = [...arr1];
console.log(arr2);
arr1.push('Sally'); // Change arr1
console.log(arr2);

運行此代碼會產生以下結果:

[ 'John', 'Sofia', 'Bob' ]
[ 'John', 'Sofia', 'Bob' ]

正如我們所見,arr2 沒有像以前那樣傳遞引用,而是填充了 arr1 作為一個全新的對象。所以即使當 arr1 更改,arr2 保持不變。

我們還可以使用擴展運算符創建數組的副本 同時添加新元素:

let arr1 = ['John', 'Sofia', 'Bob'];
let arr2 = [...arr1, 'Anthony', 'Sean'];
console.log(arr2);
['John', 'Sofia', 'Bob', 'Anthony', 'Sean']

注意: 擴展運算符適用於所有可迭代對象,包括對象。

以前這需要一行額外的代碼來將新項目添加到新數組中。

同樣,我們可以使用擴展運算符來複製對象:

let o1 = { a: 1, b: 2 };
let o2 = { c: 3, d: 4, ...o1 };
console.log(o2);
{ c: 3, d: 4, a: 1, b: 2 }

如我們所見,我們成功複製了對象 o1 進入 o2 .

此功能有許多現實世界的用例。例如,假設我們將用戶註冊信息存儲到一個對像中。我們可以對該對象進行淺拷貝,並在復制的對像中添加更多信息:

let user = { name: 'John', email: '[email protected]' };
let _user = { ...user, ...getSession(user) };
console.log(_user);

免費電子書:Git Essentials

查看我們的 Git 學習實踐指南,其中包含最佳實踐、行業認可的標準以及隨附的備忘單。停止谷歌搜索 Git 命令並真正學習 它!

{ name: 'John', email: '[email protected]', 'token': 'abc123', 'expiresAt': 1565630480671 }

我們可能還需要合併 計費和發貨信息合二為一:

const billing = { billingContact: '0987654321', billingAddress: 'street no 123, xyz city' };
const shipping = { shippingContact: '123456789', shippingAddress: 'street no 999, abc city' };
const custInfo = { ...billing, ...shipping };
console.log(custInfo);

如果我們運行這段代碼,我們應該會看到:

{
  billingContact: '0987654321',
  billingAddress: 'street no 123, xyz city',
  shippingContact: '123456789',
  shippingAddress: 'street no 999, abc city'
}

這裡可以提出一個問題。如果兩個對像有一些相同的屬性會怎樣。

在屬性衝突的情況下,最後一個對象的屬性獲勝。讓我們看一個例子:

const o1 = { a: 1, b: 2 };
const o2 = { b: 3, c: 4, ...o1};
console.log(o2);

如果您運行此代碼,您應該會看到以下內容:

{ b: 2, c: 4, a: 1 }

我們可以看到第二個對象 o2 的屬性 獲勝。但是,如果我們把展開運算符放在第一位:

const o1 = { a: 1, b: 2 };
const o2 = { ...o1, b: 3, c: 4};
console.log(o2);
{ a: 1, b: 3, c: 4 }

我們可以看到來自 o1 的屬性 獲勝,這是有道理的,因為 o2 是最後一個對象。

此功能的一個用例可能是進行默認分配:

const userProvided = {
    name: 'Bil Smith',
    email: '[email protected]',
};
const defaultValues = {
    name: 'Unknown',
    address: 'Alien',
    phone: null,
    email: null
};
const userInfo = { ...defaultValues, ...userProvided };

使用 apply() 調用函數的替代方法

假設一個函數接受一個參數 - 一個班級前 5 名學生的分數列表。我們還有一個來自外部來源的列表。當然,我們可以避免傳遞單個項目,而是使用 apply() 傳遞整個列表 方法:

myFun(m1, m2, m3, m4, m5) {
    // Do something
}

let marks = [10, 23, 83, -1, 92];
myFun.apply(undefined, arr);

我們可以擺脫令人困惑的undefined 參數並通過使用擴展運算符直接調用函數來使代碼更簡潔:

myFun(m1, m2, m3, m4, m5) {
    // Do something
}

let marks = [10, 23, 83, -1, 92];
myFun(...marks);

使用數學函數

JavaScript 有一個 Math 對象,其中包含幾種對一組數據進行操作的方法,即數據列表。

假設我們想從列表的前三個數字中獲取最大值:

let mylist = [10, 23, 83, -1, 92, -33, 76, 29, 76, 100, 644, -633];
Math.max(mylist[0], mylist[1], mylist[2]);

如果我們想獲得列表中所有數字的最大值怎麼辦?如果列表有 n 個項目怎麼辦?我們當然不想要 mylist[0], mylist[1]... mylist[1000] .

擴展運算符提供了更簡潔的解決方案:

let mylist = [10, 23, 83, -1, 92, -33, 76, 29, 76, 100, 644, -633];
Math.max(...mylist);

注意: 鑑於擴展運算符適用於數組和對象,您有時可能會想混合和匹配它們。不要那樣做!例如,以下操作將導致錯誤:

let user = {name:'John', age:28, email:'[email protected]'};
let items = [...user];
TypeError: user is not iterable

Spread Operator vs Rest 參數

擴展運算符 剩餘參數 共享相同的語法,即三個神奇的點 ... .但它們的行為完全相反。作為初學者,有時這可能會令人困惑。理解行為的底線是理解它被使用的上下文。

正如我們所了解的,展開運算符擴展了可迭代對象的內容。相比之下,rest 運算符將所有剩餘元素收集到一個數組中。

function doSum(...items) {
    let sum = 0;
    for (let item of items){
        sum += item;
    }
    return sum;
}

doSum(1);
doSum(1,2);
doSum(1, 2, 3, 4);

如果我們運行上面的代碼,我們會看到以下內容:

1
3
6
10

正如我們所見,每次剩餘元素都由 Rest Parameter 收集 .

我們還可以為某些元素提供不同的變量,並使其餘參數收集其餘項目。唯一的條件是rest參數應該永遠是函數的最後一個參數:

function doSum(times, ...items) {
    let sum = 0;
    for (let item of items){
        sum += item*times;
    }
    return sum;
}

doSum(1, 1);
doSum(2, 1, 2);
doSum(3, 1, 2, 3);

如果我們運行上面的代碼,我們將看到以下內容:

1
6
18

結論

正如我們所見,展開運算符 ... 是 JavaScript 的 ES6 規範中一個非常強大的特性。通過使用這個算子,我們可以很容易地解決很多現實世界的問題。正如我們從本文討論的各種示例中了解到的那樣,它可以讓我們編寫更少的代碼並做更多的事情。

在本文中,我們介紹了 Spread Operator 的常見用法 .我們還討論了外觀相似但不同的 Rest Parameter .請注意,根據問題的不同,可能還有許多其他用例。


Tutorial JavaScript 教程
  1. 10 個 jQuery 警報窗口和提示

  2. jQuery UI - 在外部單擊時關閉對話框

  3. 使用 ESLint 啟動並運行——可插入的 JavaScript Linter

  4. 有沒有辦法在 JavaScript 和 PHP 之間交換變量

  5. HTML 畫布 |很美麗

  6. 可重用的組件邏輯

  7. 繪圖表

  1. React Calendar 與 React Scheduler:有什麼區別以及何時使用它們

  2. 速度與激情的 Webpack

  3. JavaScript Dictionary:使用 JavaScript 創建 Dictionary 類

  4. 使用 Kubernetes 和 Container Builder 在 Google Cloud 中持續部署 NodeJS

  5. 通過 Nodemailer 發佈時從 Fetch 返回承諾

  6. const 關鍵字不會創建不可變變量

  7. JavaScript 練習網站?

  1. 慣用的 JavaScript 後端。第1部分

  2. 如何使用 Node.js 和 Cheerio 抓取網站

  3. Linting 的絕對初學者指南

  4. 構建 JavaScript 搜索欄