中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript展開運算符和剩余運算符的區別是什么

發布時間:2022-01-05 13:31:54 來源:億速云 閱讀:117 作者:iii 欄目:開發技術

這篇文章主要介紹“JavaScript展開運算符和剩余運算符的區別是什么”,在日常操作中,相信很多人在JavaScript展開運算符和剩余運算符的區別是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”JavaScript展開運算符和剩余運算符的區別是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

    JavaScript使用符號三個點(...)作為剩余運算符和展開運算符,不過這兩個運算符是有區別的。

    最主要的區別就是,剩余運算符將用戶提供的某些特定值的其余部分放入JavaScript數組中,而展開運算符則將可迭代的對象展開為單個元素。

    例如下面這段代碼,其中使用了剩余運算符將部分值存放到數組中:

    // Use rest to enclose the rest of specific user-supplied values into an array:
    function myBio(firstName, lastName, ...otherInfo) { 
      return otherInfo;
    }
    
    // Invoke myBio function while passing five arguments to its parameters:
    myBio("Oluwatobi", "Sofela", "CodeSweetly", "Web Developer", "Male");
    
    // The invocation above will return:
    ["CodeSweetly", "Web Developer", "Male"]

      查看運行結果

      上面的代碼中,我們使用...otherInfo將傳入函數myBio()參數中的剩余部分"CodeSweetly","We Developer"和"Male"存放到數組中。

      然后我們再來看下面這個例子,其中使用了展開運算符:

    // Define a function with three parameters:
    function myBio(firstName, lastName, company) { 
      return `${firstName} ${lastName} runs ${company}`;
    }
    
    // Use spread to expand an array's items into individual arguments:
    myBio(...["Oluwatobi", "Sofela", "CodeSweetly"]);
    
    // The invocation above will return:
    “Oluwatobi Sofela runs CodeSweetly”

      查看運行結果

      上面的代碼中,我們使用展開運算符(...)將數組["Oluwatobi", "Sofela", "CodeSweetly"]的內容逐一展開并傳遞給函數myBio()的參數。

      如果你對剩余運算符和展開運算符不是很熟悉,不用太擔心,本文接下來會對它們進行介紹。

      在接下來的章節中,我們將詳細討論剩余運算符和展開運算符在JavaScript中是如何工作的。

    什么是剩余運算符?

      正如上面所提到的,剩余運算符將用戶提供的某些特定值的其余部分放入JavaScript數組中。語法如下:

    ...yourValues

      上面代碼中的三個點(...)用來表示剩余運算符。

      剩余運算符之后的內容用來表示你希望填充到數組中的值。注意,只能在函數定義的最后一個參數中使用剩余運算符。

    剩余運算符在JavaScript函數中是如何工作的?

      在JavaScript函數中,剩余運算符被用在函數最后一個參數的前面。如下面的代碼:

    // Define a function with two regular parameters and one rest parameter:
    function myBio(firstName, lastName, ...otherInfo) { 
      return otherInfo;
    }

      這里,剩余運算符告訴JavaScript程序將用戶提供給參數otherInfo的任何值都添加到一個數組中。然后,將該數組賦值給otherInfo參數。

      因此,我們將...otherInfo稱之為剩余參數。

      需要注意的是,調用時傳遞給函數的實參中剩余參數是可選的。

      另一個例子:

    // Define a function with two regular parameters and one rest parameter:
    function myBio(firstName, lastName, ...otherInfo) { 
      return otherInfo;
    }
    
    // Invoke myBio function while passing five arguments to its parameters:
    myBio("Oluwatobi", "Sofela", "CodeSweetly", "Web Developer", "Male");
    
    // The invocation above will return:
    ["CodeSweetly", "Web Developer", "Male"]

      查看運行結果

      上面的代碼中,調用函數myBio()時傳入了5個參數,而函數myBio()的實參只有3個。也就是說,參數"Oluwatobi"和"Sofela"分別傳遞給了firstName和lastName,其它的參數("CodeSweetly","Web Developer"和"Male")都傳遞給了剩余參數otherInfo。所以,函數myBio()返回的結果是["CodeSweetly", "Web Developer", "Male"],它們都是剩余參數otherInfo的內容。

    注意!不能在包含剩余參數的函數體中使用"use strict"

      記住,不能在任何包含剩余參數,默認參數,或參數解構的函數體中使用"use strict"指令。否則,JavaScript將報語法錯誤。

      考慮下面的代碼:

    // Define a function with one rest parameter:
    function printMyName(...value) {
      "use strict";
      return value;
    }
    
    // The definition above will return:
    "Uncaught SyntaxError: Illegal 'use strict' directive in function with non-simple parameter list"

      注意:只有當整個腳本或封閉作用域處于strict模式時,才可以將"use strict"放到函數體外。

      現在我們知道了剩余運算符在函數中的作用,接下來我們來看看它在參數解構中是如何工作的。

    剩余運算符在參數解構中是如何工作的?

      剩余運算符在參數解構賦值時通常被用在最后一個變量的前面。下面是一個例子:

    // Define a destructuring array with two regular variables and one rest variable:
    const [firstName, lastName, ...otherInfo] = [
      "Oluwatobi", "Sofela", "CodeSweetly", "Web Developer", "Male"
    ];
    
    // Invoke the otherInfo variable:
    console.log(otherInfo); 
    
    // The invocation above will return:
    ["CodeSweetly", "Web Developer", "Male"]

      查看運行結果

      這里的剩余運算符(...)告訴JavaScript程序將用戶提供的其它值都添加到一個數組中。然后,將該數組賦值給otherInfo變量。

      因此,我們將這里的...otherInfo稱之為剩余變量。

      另一個例子:

    // Define a destructuring object with two regular variables and one rest variable:
    const { firstName, lastName, ...otherInfo } = {
      firstName: "Oluwatobi",
      lastName: "Sofela", 
      companyName: "CodeSweetly",
      profession: "Web Developer",
      gender: "Male"
    }
    
    // Invoke the otherInfo variable:
    console.log(otherInfo);
    
    // The invocation above will return:
    {companyName: "CodeSweetly", profession: "Web Developer", gender: "Male"}

      查看運行結果

      注意上面的代碼中,剩余運算符將一個屬性對象(而不是數組)賦值給otherInfo變量。也就是說,當你在解構一個對象時使用剩余運算符,它將生成一個屬性對象而非數組。

      但是,如果你在解構數組或函數時使用剩余運算符,它將生成數組字面量。

      你應該已經注意到了,在JavaScript arguments和剩余參數之間存在一些區別,下面我們來看看這些區別都有哪些。

    JavaScript arguments和剩余參數之間有哪些區別?

      下面我列出了JavaScript arguments和剩余參數之間的一些區別:

    區別1:arguments對象是一個類似于數組的對象,但它并非真正的數組!
      請記住這一點,JavaScript arguments對象不是真正的數組。它是一個類似于數組的對象,不具備數組所擁有的任何特性。

      而剩余參數是一個真正的數組,你可以在它上面使用數組所擁有的任何方法。例如,你可以對一個剩余參數使用sort()、map()、forEach()或pop()方法。但你不能對arguments對象使用這些方法。

    區別2:不能在箭頭函數中使用arguments對象
      arguments對象在箭頭函數中不可用,而剩余參數在所有的函數中都是可用的,也包括箭頭函數。

    區別3:優先使用剩余參數
      優先使用剩余參數而不是arguments對象,特別是在編寫ES6兼容代碼時。

      我們已經了解了剩余運算符是如何工作的,下面我們來討論下展開運算符,并看看它和剩余運算符之間的區別。

    什么是展開運算符以及它在JavaScript中是如何工作的?

      展開運算符(...)將一個可迭代的對象展開為單個元素。

      展開運算符可以應用在數組字面量,函數調用,以及被初始化的屬性對象中,它將可迭代對象的值逐一展開到單獨的元素中。實際上,它和剩余操作符正好相反。

      注意,只有在數組字面量,函數調用,或被初始化的屬性對象中使用展開運算符時才有效。

      下面我們來看一些實際的例子。

    示例1:展開運算符在數組字面量中如何工作

    const myName = ["Sofela", "is", "my"];
    const aboutMe = ["Oluwatobi", ...myName, "name."];
    
    console.log(aboutMe);
    
    // The invocation above will return:
    [ "Oluwatobi", "Sofela", "is", "my", "name." ]

      查看運行結果

      上面的代碼中,展開運算符(...)將數組myName拷貝到aboutMe中。

      注意:

    • 對myName的任何修改不會反映到aboutMe中。因為myName數組中的所有值都是原語。擴展操作符只是簡單地將myName數組的內容復制并粘貼到aboutMe中,而不創建任何對原始數組元素的引用。

    • 展開運算符只做淺拷貝。所以,當myName數組中包含任何非原語值時,JavaScript將在myName和aboutMe之間創建一個引用。有關展開運算符如何處理原語值和非原語值的更多信息,可以查看這里。

    • 假設我們沒有使用展開運算符來復制數組myName的內容,例如我們編寫這行代碼const aboutMe = [ "Oluwatobi", myName, "name." ] 這種情況下JavaScript將給myName分配一個引用,這樣,所有對myName數組所做的修改就都會反映到aboutMe數組中。

    示例2:如何使用展開運算符將字符串轉換為數組

    const myName = "Oluwatobi Sofela";
    
    console.log([...myName]);
    
    // The invocation above will return:
    [ "O", "l", "u", "w", "a", "t", "o", "b", "i", " ", "S", "o", "f", "e", "l", "a" ]

      查看運行結果

      上面的代碼中,我們在數組字面量中使用展開運算符([...])將myName字符串的值展開為一個數組。這樣,字符串"Oluwatobi Sofela"的內容被展開到數組[ "O", "l", "u", "w", "a", "t", "o", "b", "i", " ", "S", "o", "f", "e", "l", "a" ]中。

    示例3:展開運算符如何在函數調用中工作

    const numbers = [1, 3, 5, 7];
    
    function addNumbers(a, b, c, d) {
      return a + b + c + d;
    }
    
    console.log(addNumbers(...numbers));
    
    // The invocation above will return:
    16

      查看運行結果

      上面的代碼中,我們使用展開運算符將數組numbers的內容展開并傳遞給函數addNumbers()的參數。如果數組numbers的元素多于4個,JavaScript只會將前4個元素作為參數傳遞給函數addNumbers()而忽略其余的元素。

      下面是一些其它的例子:

    const numbers = [1, 3, 5, 7, 10, 200, 90, 59];
    
    function addNumbers(a, b, c, d) {
      return a + b + c + d;
    }
    
    console.log(addNumbers(...numbers));
    
    // The invocation above will return:
    16

      查看運行結果

    const myName = "Oluwatobi Sofela";
    
    function spellName(a, b, c) {
      return a + b + c;
    }
    
    console.log(spellName(...myName));      // returns: "Olu"
    
    console.log(spellName(...myName[3]));   // returns: "wundefinedundefined"
    
    console.log(spellName([...myName]));    // returns: "O,l,u,w,a,t,o,b,i, ,S,o,f,e,l,aundefinedundefined"
    
    console.log(spellName({...myName}));    // returns: "[object Object]undefinedundefined"

      查看運行結果 

    示例4:展開運算符在對象字面量中如何工作

    const myNames = ["Oluwatobi", "Sofela"];
    const bio = { ...myNames, runs: "codesweetly.com" };
    
    console.log(bio);
    
    // The invocation above will return:
    { 0: "Oluwatobi", 1: "Sofela", runs: "codesweetly.com" }

      查看運行結果

      上面的代碼中,我們在bio對象內部使用展開運算符將數組myNames的值展開為各個屬性。

    有關展開運算符我們需要知道的

      當使用展開運算符時,請記住以下三個基本信息。

    1. 展開運算符不能展開對象字面量的值

      由于屬性對象是非可迭代對象,所以不能使用展開運算符將它的值進行展開。但是,你可以使用展開運算符將一個對象的屬性克隆到另一個對象中。

      看下面這個例子:

    const myName = { firstName: "Oluwatobi", lastName: "Sofela" };
    const bio = { ...myName, website: "codesweetly.com" };
    
    console.log(bio);
    
    // The invocation above will return:
    { firstName: "Oluwatobi", lastName: "Sofela", website: "codesweetly.com" };

      查看運行結果

      上面的代碼中,我們使用展開運算符將myName對象的內容克隆到了bio對象中。

      注意:

    • 展開運算符只能展開可迭代對象的值。

    • 只有當一個對象包含一個帶有@@iterator key的屬性時,才是一個可迭代的對象。

    • Array,TypedArray,String,Map,Set都是內置的可迭代類型,因為它們默認都帶有@@iterator屬性。

    • 屬性對象是非可迭代數組類型,因為默認情況下它沒有@@iterator屬性。

    • 可以在屬性對象上添加@@iterator使其成為可迭代對象。

    2. 展開運算符不克隆相同的屬性

      假設我們使用展開運算符將對象A的屬性克隆到對象B中,如果對象B包含與對象A中相同的屬性,那么對象B的屬性將覆蓋對象A的屬性。換句話說,在這個過程中,對象A中那些與對象B相同的屬性不會被克隆。

      看下面這個例子:

    const myName = { firstName: "Tobi", lastName: "Sofela" };
    const bio = { ...myName, firstName: "Oluwatobi", website: "codesweetly.com" };
    
    console.log(bio);
    
    // The invocation above will return:
    { firstName: "Oluwatobi", lastName: "Sofela", website: "codesweetly.com" };

      查看運行結果

      注意,展開運算符沒有將myName對象的firstName屬性的值復制到bio對象中,因為對象bio中已經包含firstName屬性了。

    3. 注意展開運算符在包含非原語的對象中是何如工作的

      如果在只包含原語值的對象(或數組)上使用展開運算符,JavaScript不會在原對象和復制對象之間創建任何引用。

      看下面這段代碼:

    const myName = ["Sofela", "is", "my"];
    const aboutMe = ["Oluwatobi", ...myName, "name."];
    
    console.log(aboutMe);
    
    // The invocation above will return:
    ["Oluwatobi", "Sofela", "is", "my", "name."]

      查看運行結果

      注意,myName中的每一個元素都是一個原語值,因此,當我們使用展開運算符將myName克隆到aboutMe時,JavaScript不會在兩個數組之間創建任何引用。所以,對myName數組所做的任何修改都不會反映到aboutMe數組中,反之亦然。

      讓我們給myName數組添加一個元素:

    myName.push("real");

      現在我們來檢查一下myName和aboutMe的值:

    console.log(myName); // ["Sofela", "is", "my", "real"]
    
    console.log(aboutMe); // ["Oluwatobi", "Sofela", "is", "my", "name."]

      請注意,我們對myName數組的修改并沒有反映到aboutMe數組中,因為展開運算符并沒有在原始數組和復制數組之間創建任何引用。

    如果myName數組包含非原語項呢?

      假設myName包含非原語項,這種情況下,展開運算符將在原數組的非原語項和克隆項之間創建一個引用。

      看下面的例子:

    const myName = [["Sofela", "is", "my"]];
    const aboutMe = ["Oluwatobi", ...myName, "name."];
    
    console.log(aboutMe);
    
    // The invocation above will return:
    [ "Oluwatobi", ["Sofela", "is", "my"], "name." ]

      查看運行結果

      注意,這里的myName數組包含一個非原語項。

      因此,當使用展開運算符將myName的內容克隆到aboutMe時,JavaScript將在兩個數組之間創建一個引用。這樣,任何對myName數組的修改都會反映到aboutMe數組中,反之亦然。

      作為例子,我們同樣給myName數組添加一個元素:

    myName[0].push("real");

      現在我們來查看myName和aboutMe的值:

    console.log(myName); // [["Sofela", "is", "my", "real"]]
    
    console.log(aboutMe); // ["Oluwatobi", ["Sofela", "is", "my", "real"], "name."]

      查看運行結果

      注意,對myName數組的修改內容反映到了aboutMe數組中,因為展開運算符在原始數組和復制數組之間創建了一個引用。

      另外一個例子:

    const myName = { firstName: "Oluwatobi", lastName: "Sofela" };
    const bio = { ...myName };
    
    myName.firstName = "Tobi";
    
    console.log(myName); // { firstName: "Tobi", lastName: "Sofela" }
    
    console.log(bio); // { firstName: "Oluwatobi", lastName: "Sofela" }

      查看運行結果

      上面的代碼中,myName的更新內容沒有反映到bio對象中,因為我們在只包含原語值的對象上使用展開運算符。

      注意,開發人員通常將這里的myName稱之為淺對象,因為它只包含原語項。

      另外一個例子:

    const myName = { 
      fullName: { firstName: "Oluwatobi", lastName: "Sofela" }
    };
    
    const bio = { ...myName };
    
    myName.fullName.firstName = "Tobi";
    
    console.log(myName); // { fullName: { firstName: "Tobi", lastName: "Sofela" } }
    
    console.log(bio); // { fullName: { firstName: "Tobi", lastName: "Sofela" } }

      查看運行結果

      上面的代碼中,myName的更新內容被反映到bio對象中,因為我們在包含非原語值的對象上使用了展開運算符。

      注意:

    • 我們稱這里的myName為深對象,因為它包含非原語項。

    • 將一個對象克隆到另一個對象時,如果創建了引用,則進行的是淺拷貝。例如,...myName產生了myName對象的一個淺拷貝,因為你對其中一個對象所做的任何修改都會反映到另一個對象中。

    • 將一個對象克隆到另一個對象時,如果沒有創建引用,則進行的時深拷貝。例如,我可以通過const bio = JSON.parse(JSON.stringify(myName))將myName對象深拷貝到bio對象中。如此一來,JavaScript將把myName克隆到bio中而不創建任何引用。

    • 我們可以通過用一個新對象來替換myName或bio中的fullName子對象,從而切斷myName和bio之間的引用。例如,使用myName.fullName = { firstName: "Tobi", lastName: "Sofela" }來斷開myName和bio之間的指針。

    到此,關于“JavaScript展開運算符和剩余運算符的區別是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    浦北县| 凤城市| 彰化县| 柳河县| 汽车| 沭阳县| 汝城县| 健康| 宜都市| 深水埗区| 文昌市| 米泉市| 蕲春县| 西安市| 黎城县| 新巴尔虎右旗| 师宗县| 罗城| 新竹县| 手机| 定边县| 建水县| 宜宾县| 龙里县| 仁寿县| 潮州市| 荣昌县| 株洲县| 江永县| 清苑县| 桃源县| 河池市| 柘荣县| 友谊县| 织金县| 手游| 江口县| 文成县| 左贡县| 平远县| 科尔|