亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript展開運算符和剩余運算符的區(qū)別詳解

 更新時間:2022年01月05日 11:27:30   作者:Jaxu  
本文主要介紹了JavaScript展開運算符和剩余運算符的區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

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

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

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

// 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"]

  查看運行結(jié)果

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

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

// 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”

  查看運行結(jié)果

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

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

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

什么是剩余運算符?

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

...yourValues

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

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

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

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

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

  這里,剩余運算符告訴JavaScript程序?qū)⒂脩籼峁┙o參數(shù)otherInfo的任何值都添加到一個數(shù)組中。然后,將該數(shù)組賦值給otherInfo參數(shù)。

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

  需要注意的是,調(diào)用時傳遞給函數(shù)的實參中剩余參數(shù)是可選的。

  另一個例子:

// 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"]

  查看運行結(jié)果

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

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

  記住,不能在任何包含剩余參數(shù),默認(rèn)參數(shù),或參數(shù)解構(gòu)的函數(shù)體中使用"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"

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

  現(xiàn)在我們知道了剩余運算符在函數(shù)中的作用,接下來我們來看看它在參數(shù)解構(gòu)中是如何工作的。

剩余運算符在參數(shù)解構(gòu)中是如何工作的?

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

// 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"]

  查看運行結(jié)果

  這里的剩余運算符(...)告訴JavaScript程序?qū)⒂脩籼峁┑钠渌刀继砑拥揭粋€數(shù)組中。然后,將該數(shù)組賦值給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"}

  查看運行結(jié)果

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

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

  你應(yīng)該已經(jīng)注意到了,在JavaScript arguments和剩余參數(shù)之間存在一些區(qū)別,下面我們來看看這些區(qū)別都有哪些。

JavaScript arguments和剩余參數(shù)之間有哪些區(qū)別?

  下面我列出了JavaScript arguments和剩余參數(shù)之間的一些區(qū)別:

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

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

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

區(qū)別3:優(yōu)先使用剩余參數(shù)
  優(yōu)先使用剩余參數(shù)而不是arguments對象,特別是在編寫ES6兼容代碼時。

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

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

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

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

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

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

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

const myName = ["Sofela", "is", "my"];
const aboutMe = ["Oluwatobi", ...myName, "name."];

console.log(aboutMe);

// The invocation above will return:
[ "Oluwatobi", "Sofela", "is", "my", "name." ]

  查看運行結(jié)果

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

  注意:

  • 對myName的任何修改不會反映到aboutMe中。因為myName數(shù)組中的所有值都是原語。擴展操作符只是簡單地將myName數(shù)組的內(nèi)容復(fù)制并粘貼到aboutMe中,而不創(chuàng)建任何對原始數(shù)組元素的引用。
  • 展開運算符只做淺拷貝。所以,當(dāng)myName數(shù)組中包含任何非原語值時,JavaScript將在myName和aboutMe之間創(chuàng)建一個引用。有關(guān)展開運算符如何處理原語值和非原語值的更多信息,可以查看這里。
  • 假設(shè)我們沒有使用展開運算符來復(fù)制數(shù)組myName的內(nèi)容,例如我們編寫這行代碼const aboutMe = [ "Oluwatobi", myName, "name." ] 這種情況下JavaScript將給myName分配一個引用,這樣,所有對myName數(shù)組所做的修改就都會反映到aboutMe數(shù)組中。

示例2:如何使用展開運算符將字符串轉(zhuǎn)換為數(shù)組

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" ]

  查看運行結(jié)果

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

示例3:展開運算符如何在函數(shù)調(diào)用中工作

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

  查看運行結(jié)果

  上面的代碼中,我們使用展開運算符將數(shù)組numbers的內(nèi)容展開并傳遞給函數(shù)addNumbers()的參數(shù)。如果數(shù)組numbers的元素多于4個,JavaScript只會將前4個元素作為參數(shù)傳遞給函數(shù)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

  查看運行結(jié)果

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"

  查看運行結(jié)果 

示例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" }

  查看運行結(jié)果

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

有關(guān)展開運算符我們需要知道的

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

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

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

  看下面這個例子:

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" };

  查看運行結(jié)果

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

  注意:

  • 展開運算符只能展開可迭代對象的值。
  • 只有當(dāng)一個對象包含一個帶有@@iterator key的屬性時,才是一個可迭代的對象。
  • Array,TypedArray,String,Map,Set都是內(nèi)置的可迭代類型,因為它們默認(rèn)都帶有@@iterator屬性。
  • 屬性對象是非可迭代數(shù)組類型,因為默認(rèn)情況下它沒有@@iterator屬性。
  • 可以在屬性對象上添加@@iterator使其成為可迭代對象。

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

  假設(shè)我們使用展開運算符將對象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" };

  查看運行結(jié)果

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

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

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

  看下面這段代碼:

const myName = ["Sofela", "is", "my"];
const aboutMe = ["Oluwatobi", ...myName, "name."];

console.log(aboutMe);

// The invocation above will return:
["Oluwatobi", "Sofela", "is", "my", "name."]

  查看運行結(jié)果

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

  讓我們給myName數(shù)組添加一個元素:

myName.push("real");

  現(xiàn)在我們來檢查一下myName和aboutMe的值:

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

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

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

如果myName數(shù)組包含非原語項呢?

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

  看下面的例子:

const myName = [["Sofela", "is", "my"]];
const aboutMe = ["Oluwatobi", ...myName, "name."];

console.log(aboutMe);

// The invocation above will return:
[ "Oluwatobi", ["Sofela", "is", "my"], "name." ]

  查看運行結(jié)果

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

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

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

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

  現(xiàn)在我們來查看myName和aboutMe的值:

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

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

  查看運行結(jié)果

  注意,對myName數(shù)組的修改內(nèi)容反映到了aboutMe數(shù)組中,因為展開運算符在原始數(shù)組和復(fù)制數(shù)組之間創(chuàng)建了一個引用。

  另外一個例子:

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" }

  查看運行結(jié)果

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

  注意,開發(fā)人員通常將這里的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" } }

  查看運行結(jié)果

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

  注意:

  • 我們稱這里的myName為深對象,因為它包含非原語項。
  • 將一個對象克隆到另一個對象時,如果創(chuàng)建了引用,則進(jìn)行的是淺拷貝。例如,...myName產(chǎn)生了myName對象的一個淺拷貝,因為你對其中一個對象所做的任何修改都會反映到另一個對象中。
  • 將一個對象克隆到另一個對象時,如果沒有創(chuàng)建引用,則進(jìn)行的時深拷貝。例如,我可以通過const bio = JSON.parse(JSON.stringify(myName))將myName對象深拷貝到bio對象中。如此一來,JavaScript將把myName克隆到bio中而不創(chuàng)建任何引用。
  • 我們可以通過用一個新對象來替換myName或bio中的fullName子對象,從而切斷myName和bio之間的引用。例如,使用myName.fullName = { firstName: "Tobi", lastName: "Sofela" }來斷開myName和bio之間的指針。

結(jié)語

  本文討論了剩余操作符和展開操作符之間的區(qū)別,并通過示例說明了它們在JavaScript中是如何工作的。

到此這篇關(guān)于JavaScript展開運算符和剩余運算符的區(qū)別詳解的文章就介紹到這了,更多相關(guān)JavaScript展開運算符和剩余運算符 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論