欧美亚洲中文,在线国自产视频,欧洲一区在线观看视频,亚洲综合中文字幕在线观看

      1. <dfn id="rfwes"></dfn>
          <object id="rfwes"></object>
        1. 站長(zhǎng)資訊網(wǎng)
          最全最豐富的資訊網(wǎng)站

          一文詳解JavaScript函數(shù)中的參數(shù)

          函數(shù)參數(shù)是函數(shù)內(nèi)部跟函數(shù)外部溝通的橋梁。下面本篇文章就來(lái)帶大家了解一下JavaScript函數(shù)中的參數(shù),希望對(duì)大家有所幫助!

          一文詳解JavaScript函數(shù)中的參數(shù)

          一、函數(shù)的形參和實(shí)參

          函數(shù)的參數(shù)會(huì)出現(xiàn)在兩個(gè)地方,分別是函數(shù)定義處和函數(shù)調(diào)用處,這兩個(gè)地方的參數(shù)是有區(qū)別的。

          • 形參(形式參數(shù))

            在函數(shù)定義中出現(xiàn)的參數(shù)可以看做是一個(gè)占位符,它沒(méi)有數(shù)據(jù),只能等到函數(shù)被調(diào)用時(shí)接收傳遞進(jìn)來(lái)的數(shù)據(jù),所以稱(chēng)為形式參數(shù),簡(jiǎn)稱(chēng)形參。

          • 實(shí)參(實(shí)際參數(shù))

            函數(shù)被調(diào)用時(shí)給出的參數(shù)包含了實(shí)實(shí)在在的數(shù)據(jù),會(huì)被函數(shù)內(nèi)部的代碼使用,所以稱(chēng)為實(shí)際參數(shù),簡(jiǎn)稱(chēng)實(shí)參。

          形參和實(shí)參的區(qū)別和聯(lián)系

          • 1) 形參變量只有在函數(shù)被調(diào)用時(shí)才會(huì)分配內(nèi)存,調(diào)用結(jié)束后,立刻釋放內(nèi)存,所以形參變量只有在函數(shù)內(nèi)部有效,不能在函數(shù)外部使用。

          • 2) 實(shí)參可以是常量、變量、表達(dá)式、函數(shù)等,無(wú)論實(shí)參是何種類(lèi)型的數(shù)據(jù),在進(jìn)行函數(shù)調(diào)用時(shí),它們都必須有確定的值,以便把這些值傳送給形參,所以應(yīng)該提前用賦值、輸入等辦法使實(shí)參獲得確定值。

          • 3) 實(shí)參和形參在數(shù)量上、類(lèi)型上、順序上必須嚴(yán)格一致,否則會(huì)發(fā)生“類(lèi)型不匹配”的錯(cuò)誤。當(dāng)然,如果能夠進(jìn)行自動(dòng)類(lèi)型轉(zhuǎn)換,或者進(jìn)行了強(qiáng)制類(lèi)型轉(zhuǎn)換,那么實(shí)參類(lèi)型也可以不同于形參類(lèi)型。

          • 4) 函數(shù)調(diào)用中發(fā)生的數(shù)據(jù)傳遞是單向的,只能把實(shí)參的值傳遞給形參,而不能把形參的值反向地傳遞給實(shí)參;換句話(huà)說(shuō),一旦完成數(shù)據(jù)的傳遞,實(shí)參和形參就再也沒(méi)有瓜葛了,所以,在函數(shù)調(diào)用過(guò)程中,形參的值發(fā)生改變并不會(huì)影響實(shí)參。

          • 5) 形參和實(shí)參雖然可以同名,但它們之間是相互獨(dú)立的,互不影響,因?yàn)閷?shí)參在函數(shù)外部有效,而形參在函數(shù)內(nèi)部有效。

          形參和實(shí)參的功能是傳遞數(shù)據(jù),發(fā)生函數(shù)調(diào)用時(shí),實(shí)參的值會(huì)傳遞給形參。

          二、參數(shù)傳遞

          函數(shù)允許我們將數(shù)據(jù)傳遞進(jìn)去,通過(guò)傳遞的數(shù)據(jù)從而影響函數(shù)執(zhí)行結(jié)果,使函數(shù)更靈活、復(fù)用性更強(qiáng)。

          function foo(a, b) {     console.log([a, b]); }  foo(1, 2); // 輸出 [1, 2]

          這個(gè)例子中,ab 屬于函數(shù)中的局部變量,只能在函數(shù)中訪(fǎng)問(wèn)。調(diào)用函數(shù)時(shí),傳遞的數(shù)據(jù)會(huì)根據(jù)位置來(lái)匹配對(duì)應(yīng),分別賦值給 ab。

          創(chuàng)建函數(shù)時(shí),function 函數(shù)名 后面括號(hào)中設(shè)定的參數(shù)被稱(chēng)為形參;調(diào)用函數(shù)時(shí),函數(shù)名后面括號(hào)中傳入的參數(shù)被稱(chēng)為實(shí)參。上面例子中,ab 是形參,傳入的 12 是實(shí)參。

          因?yàn)樾螀⑹且崖暶鞯淖兞浚圆荒茉儆?letconst 重復(fù)聲明。

          function foo(a, b) {     let a = 1; // 報(bào)錯(cuò),a 已聲明     const b = 1; // 報(bào)錯(cuò),b 已聲明 }

          JavaScript 中所有函數(shù)傳遞都是按值傳遞的,不會(huì)按引用傳遞。所謂的值,就是指直接保存在變量上的值,如果把對(duì)象作為參數(shù)傳遞,那么這個(gè)值就是這個(gè)對(duì)象的引用,而不是對(duì)象本身。這里實(shí)際上是一個(gè)隱式的賦值過(guò)程,所以給函數(shù)傳遞參數(shù)時(shí),相當(dāng)于從一個(gè)變量賦值到另一個(gè)變量。

          原始值:

          function add(num) {     return num + 1; }  let count = 5; let result = add(count); // 此處參數(shù)傳遞的過(guò)程可以看作是 num = count  console.log(count); // 5 console.log(result); // 6

          引用值:

          function setName(obj) {     obj.name = "小明"; }  let person = {};  setName(person); // 此處參數(shù)傳遞的過(guò)程可以看作是 obj = person; console.log(person); // {name: "小明"}

          三、理解參數(shù)

          JavaScript 中的函數(shù)既不會(huì)檢測(cè)參數(shù)的類(lèi)型,也不會(huì)檢測(cè)傳入?yún)?shù)的個(gè)數(shù)。定義函數(shù)時(shí)設(shè)置兩個(gè)形參,不意味著調(diào)用時(shí)必須傳入兩個(gè)參數(shù)。實(shí)際調(diào)用時(shí)不管是傳了一個(gè)還是三個(gè),甚至不傳參數(shù)也不會(huì)報(bào)錯(cuò)。

          所有函數(shù)(非箭頭)中都有一個(gè)名為 arguments 的特殊的類(lèi)數(shù)組對(duì)象(不是 Array 的實(shí)例),它保存著所有實(shí)參的副本,我們可以通過(guò)它按照數(shù)組的索引訪(fǎng)問(wèn)方式獲取所有實(shí)參的值,也可以訪(fǎng)問(wèn)它的 arguments.length 屬性來(lái)確定函數(shù)實(shí)際調(diào)用時(shí)傳入的參數(shù)個(gè)數(shù)。

          例如:

          function foo(a, b) { 	console.log(arguments[0]);     console.log(arguments[1]);     console.log(arguments.length); }  foo(10, 20); // 依次輸出 10、20、2

          上面例子中,foo() 函數(shù)的第一個(gè)參數(shù)是 a,第二個(gè)參數(shù)是b ,可以通過(guò) arguments[x] 的方式來(lái)分別獲取同樣的值 。因此,你甚至可以在聲明函數(shù)時(shí)不設(shè)置形參。

          function foo() { 	console.log(arguments[0]);     console.log(arguments[1]); }  foo(10, 20); // 依次輸出 10、20

          由此可見(jiàn),JavaScript 函數(shù)的形參只是方便使用才寫(xiě)出來(lái)的。想傳多少個(gè)參數(shù)都不會(huì)產(chǎn)生錯(cuò)誤。

          還有一個(gè)要注意的是,arguments 可以跟形參一起使用,并且 arguments 對(duì)象中的值會(huì)和對(duì)應(yīng)的形參保持同步。例如:

          function foo(a) { 	arguments[0] ++;     console.log(a); }  foo(10); // 輸出 11 //------------------------------------ function foo2(a) { 	a++;     console.log(arguments[0]); }  foo2(10); // 輸出 11

          當(dāng)修改 arguments[0] 或 a 的值時(shí),另一個(gè)也被改變了。這并不意味著它們?cè)L問(wèn)同一個(gè)內(nèi)存地址,畢竟我們傳入的是一個(gè)原始值。它們?cè)趦?nèi)存中還是分開(kāi)的,只是由于內(nèi)部的機(jī)制使它們的值保持了同步。

          另外,如果缺少傳參,那這個(gè)形參的值就不會(huì)和 arguments 對(duì)象中的對(duì)應(yīng)值進(jìn)行同步。例如下面這個(gè)例子,只傳了一個(gè)參數(shù),那么arguments 中只有一個(gè)實(shí)參值,這時(shí)候在函數(shù)中把 arguments[1] 設(shè)置為某個(gè)值,這個(gè)值并不會(huì)同步給第二個(gè)形參,例如:

          function foo(a,b) {     arguments[1] = 2;     console.log(b); }  foo(1); // 輸出 undefined

          這個(gè)例子中,形參 b 沒(méi)有傳入實(shí)參,它的值會(huì)默認(rèn)為 undefined。但如果:

          foo(1, undefined); // 輸出 2

          手動(dòng)傳入 undefined 時(shí), arguments 數(shù)組中會(huì)出現(xiàn)一個(gè)值為 undefined 的元素,依然能和 b 的值進(jìn)行同步。

          嚴(yán)格模式下,arguments 對(duì)象中的值和形參不會(huì)再同步,當(dāng)然,如果傳入的是引用值,它們依然會(huì)互相影響,但這只是引用值的特性而已。因此,在開(kāi)發(fā)中最好不要依賴(lài)這種同步機(jī)制,也就是說(shuō)不要同時(shí)使用形參和它在arguments 對(duì)象中的對(duì)應(yīng)值。

          箭頭函數(shù)中沒(méi)有 arguments

          如果函數(shù)是使用箭頭語(yǔ)法定義的,那么函數(shù)中是沒(méi)有 arguments 對(duì)象的,只能通過(guò)定義的形參來(lái)訪(fǎng)問(wèn)。

          let foo = () => {     console.log(arguments[0]); }foo(); // 報(bào)錯(cuò),arguments 未定義

          在某些情況可能會(huì)訪(fǎng)問(wèn)到 arguments

          function fn1(){     let fn2 = () => {     	console.log(arguments[0]);     }          fn2(); }fn1(5);

          但這個(gè) arguments,并不是箭頭函數(shù)的,而是屬于外部普通函數(shù)的,當(dāng)箭頭函數(shù)中訪(fǎng)問(wèn) arguments 時(shí),順著作用域鏈找到了外部函數(shù)的arguments

          四、將對(duì)象屬性用作實(shí)參

          當(dāng)一個(gè)函數(shù)包含的形參有多個(gè)時(shí),調(diào)用函數(shù)就成了一種麻煩,因?yàn)槟憧偸且WC傳入的參數(shù)放在正確的位置上,有沒(méi)有辦法解決傳參順序的限制呢?

          由于對(duì)象屬性是無(wú)序的,通過(guò)屬性名來(lái)確定對(duì)應(yīng)的值。因此可以通過(guò)傳入對(duì)象的方式,以對(duì)象中的屬性作為真正的實(shí)參,這樣參數(shù)的順序就無(wú)關(guān)緊要了。

          function foo(obj) {     console.log(obj.name, obj.sex, obj.age); }  foo({ sex: '男', age: 18, name: '小明' }); // 小明 男 18

          五、參數(shù)默認(rèn)值

          如果調(diào)用函數(shù)時(shí)缺少提供實(shí)參,那么形參默認(rèn)值為 undefined

          有時(shí)候我們想要設(shè)置特定的默認(rèn)值,在 ES6 之前還不支持顯式地設(shè)置默認(rèn)值的時(shí)候,只能采用變通的方式:

          function sayHi(name) {     name = name || 'everyone';      	console.log( 'Hello ' + name + '!'); }  sayHi(); // 輸出 'Hello everyone!'

          通過(guò)檢查參數(shù)值的方式判斷有沒(méi)有賦值,上面的做法雖然簡(jiǎn)便,但缺點(diǎn)在于如果傳入的實(shí)參對(duì)應(yīng)布爾值為 false ,實(shí)參就不起作用了。需要更精確的話(huà)可以用 if 語(yǔ)句或者三元表達(dá)式,判斷參數(shù)是否等于 undefined,如果是則說(shuō)明這個(gè)參數(shù)缺失 :

          // if 語(yǔ)句判斷 function sayHi(name) { 	if (name === undefined) { 		name = 'everyone'; 	}      	console.log( 'Hello ' + name + '!'); }  // 三元表達(dá)式判斷 function sayHi(name) { 	name =  (name !== undefined) ? name : 'everyone'; 	     console.log( 'Hello ' + name + '!'); }

          ES6 就方便了許多,因?yàn)樗С至孙@式的設(shè)置默認(rèn)值的方式,就像這樣:

          function sayHi(name = 'everyone') { // 定義函數(shù)時(shí),直接給形參賦值 	console.log( 'Hello ' + name + '!'); }  sayHi(); // 輸出 'Hello everyone!'  sayHi('Tony'); // 輸出 'Hello Tony!'  sayHi(undefined); // 輸出 'Hello everyone!'

          這些結(jié)果表明了,它也是通過(guò)參數(shù)是否等于 undefined 來(lái)判定參數(shù)是否缺失的。

          默認(rèn)值不但可以是一個(gè)值,它還可以是任意合法的表達(dá)式,甚至是函數(shù)調(diào)用:

          function sayHi(name = 'every'+'one') { 	console.log( 'Hello ' + name + '!'); }  sayHi(); // 輸出 'Hello everyone!'  //-------------------------------------- function foo() {     console.log('調(diào)用foo');     return 'Tony'; }  function sayHi(name = foo()) { 	console.log( 'Hello ' + name + '!'); } 		   sayHi(); // 輸出 '調(diào)用foo'          // 輸出 'Hello Tony!'   sayHi(undefined); // 輸出 '調(diào)用foo'                   // 輸出 'Hello Tony!'   sayHi('John'); // 輸出 'Hello John!'

          可以看到,函數(shù)參數(shù)的默認(rèn)值只有在函數(shù)調(diào)用時(shí),參數(shù)的值缺失或者是 undefined 才會(huì)求值,不會(huì)在函數(shù)定義時(shí)求值。

          參數(shù)默認(rèn)值的位置

          通常我們給參數(shù)設(shè)置默認(rèn)值,是為了調(diào)用函數(shù)時(shí)可以適當(dāng)省略參數(shù)的傳入,這里要注意的是,有多個(gè)參數(shù)時(shí),設(shè)置了默認(rèn)值的參數(shù)如果不是放在尾部,實(shí)際上它是無(wú)法省略的。

          function fn(x = 1, y) { 	console.log([x, y]); }  fn(); // 輸出 [1, undefined] fn(2); // 輸出 [2, undefined] fn(, 2); // 報(bào)錯(cuò),語(yǔ)法錯(cuò)誤(這里不支持像數(shù)組那樣的空槽) fn(undefined, 2); // 輸出 [1, 2] (那還不如傳個(gè) 1 方便呢!)

          上面例子中,給形參 x 設(shè)置的默認(rèn)值就顯得沒(méi)有任何意義了。因此,設(shè)置默認(rèn)值的參數(shù)放在尾部是最好的做法:

          function fn(x, y = 2) { 	console.log([x, y]); }  fn(); // 輸出 [undefined, 2] fn(1); // 輸出 [1, 2] fn(1, 1) // 輸出 [1, 1]

          參數(shù)的省略問(wèn)題

          在多個(gè)參數(shù)設(shè)置了默認(rèn)值的情況下,那么問(wèn)題又來(lái)了,你并不能省略比較靠前的參數(shù),而只給最后的一個(gè)參數(shù)傳入實(shí)參。

          function fn(x, y = 2, z = 3) { 	console.log([x, y, z]); }  fn(1, , 10) // 報(bào)錯(cuò)

          前面我們知道,可以通過(guò)傳入對(duì)象的這種方式去避免參數(shù)順序的限制。那參數(shù)默認(rèn)值如何實(shí)現(xiàn)呢?用 ||if 語(yǔ)句或者三元表達(dá)式去判斷也是解決辦法,但這樣就顯得有些落后了。接下來(lái)要討論的是另外兩種 ES6 中的全新方式。

          參數(shù)默認(rèn)值和 Object.assign() 結(jié)合使用

          function fn(obj = {}) {     let defaultObj = {         x: undefined,         y: 2,         z: 3     }          let result = Object.assign(defaultObj, obj);      	console.log([result.x, result.y, result.z]); }  fn(); // 輸出 [undefined, 2, 3] fn({ x: 1, z: 10 }); // 輸出 [1, 2, 10]

          上面的例子中,在函數(shù)中定義了一個(gè)對(duì)象 defaultObj ,變通地利用其中的屬性作為參數(shù)的默認(rèn)值,然后利用 Object.assagin() 把傳入的對(duì)象和默認(rèn)對(duì)象進(jìn)行合并,defaultObj 中的屬性會(huì)被 obj 的相同屬性覆蓋,obj 中如果有其他屬性會(huì)分配給 defaultObj 。這里用一個(gè)變量接收返回的合并對(duì)象。

          同時(shí)形參 obj 也設(shè)置了默認(rèn)值為一個(gè)空對(duì)象,防止函數(shù)調(diào)用時(shí)不傳任何參數(shù),因?yàn)檫@會(huì)導(dǎo)致 Object.assign() 接收的第二個(gè)參數(shù)是 undefined ,從而產(chǎn)生報(bào)錯(cuò)。

          參數(shù)默認(rèn)值和解構(gòu)賦值結(jié)合使用

          函數(shù)調(diào)用時(shí),實(shí)參和形參的匹配實(shí)際上是一個(gè)隱式的賦值過(guò)程,所以,參數(shù)傳遞也可以進(jìn)行解構(gòu)賦值:

          function fn({ x, y = 2, z = 3 }) {     console.log([x, y, z]); }  fn({}); // 輸出 [undefined, 2, 3] fn({ x: 1, z: 10 }); // 輸出 [1, 2, 10]

          在這個(gè)例子中,使用的只是對(duì)象的解構(gòu)賦值默認(rèn)值,還沒(méi)有使用函數(shù)參數(shù)的默認(rèn)值。如果函數(shù)調(diào)用時(shí)不傳任何參數(shù),也會(huì)產(chǎn)生報(bào)錯(cuò),因?yàn)檫@導(dǎo)致了參數(shù)初始化時(shí)解構(gòu)賦值失敗,相當(dāng)于執(zhí)行了 {x, y = 2, z = 3} = undefined 這樣的代碼。

          同樣的,你可以利用參數(shù)默認(rèn)值的語(yǔ)法,給 {x, y = 2, z = 3} 設(shè)置一個(gè)默認(rèn)的解構(gòu)對(duì)象,使得不傳參函數(shù)也能夠順利執(zhí)行:

          function fn({ x, y = 2, z = 3 } = {}) {     console.log([x, y, z]); }  fn(); // 輸出 [undefined, 2, 3]

          這里出現(xiàn)了雙重的默認(rèn)值,可能有些繞,那么用一段偽代碼來(lái)解釋以上的參數(shù)初始化過(guò)程就是:

          if( 實(shí)參 === {...} ) { // 當(dāng) fn({...});          { x, y = 2, z = 3 } = {...};                          } else if ( 實(shí)參 === undefined ){ // 當(dāng) fn();     { x, y = 2, z = 3 } = {};  }

          雙重默認(rèn)值有一點(diǎn)細(xì)節(jié)需要特別注意,就是解構(gòu)賦值默認(rèn)值和函數(shù)參數(shù)默認(rèn)值的差別,看下面例子:

          function fn ({ x = 1 } = {}, { y } = { y: 2 }){     console.log(x, y); }  fn(); // 輸出 1 2 fn({ x: 10 }, { y: 20 }); // 輸出 10 20 fn({},{}); // 1 undefined

          這個(gè)函數(shù)中,有兩組參數(shù)采用了解構(gòu)賦值的方式,看似 x 和 y 都設(shè)置了默認(rèn)值,雖然是不同的兩種形式,但顯然不是任何情況下結(jié)果都相同的。當(dāng)傳入的參數(shù)是{}時(shí),y 并沒(méi)有獲取到默認(rèn)值 2 ,為什么會(huì)這樣呢?結(jié)合前面的偽代碼例子來(lái)看:

          fn({ x: 10 }, { y: 20 }); // 初始化時(shí): { x = 1 } = { x: 10 }, { y } = { y: 20 }  fn({},{}); // 初始化時(shí): { x = 1 } = {}, { y } = {}

          當(dāng)傳入的參數(shù)是{}時(shí),函數(shù)參數(shù)沒(méi)有缺失也不是 undefined ,所以函數(shù)參數(shù)默認(rèn)值是不起作用的。同時(shí) {} 里面也沒(méi)有 x 和 y 的對(duì)應(yīng)值,x 得到的 1 是解構(gòu)賦值默認(rèn)值,而 y 由于沒(méi)有設(shè)置解構(gòu)賦值默認(rèn)值,所以它默認(rèn)是 undefined。

          參數(shù)默認(rèn)值的作用域與暫時(shí)性死區(qū)

          還有一個(gè)小細(xì)節(jié),一旦有參數(shù)設(shè)置了默認(rèn)值,那么它們會(huì)形成自己的作用域(包裹在(...)中),因此不能引用函數(shù)體中的變量:

          function foo(a = b) {     let b = 1; }  foo(); // 報(bào)錯(cuò),b 未定義

          但這個(gè)作用域只是臨時(shí)的,參數(shù)初始化完畢后,這個(gè)作用域就不存在了。

          它也符合普通作用域的規(guī)則:

          let b = 2;  function foo(a = b) {     let b = 1;     return a; }  foo(); // 2

          上面例子中,存在一個(gè)全局變量 b,那么形參 a 會(huì)獲取到全局變量 b 的值。

          當(dāng)然,如果形參作用域中存在一個(gè)形參 b 的話(huà),它優(yōu)先獲取到的是當(dāng)前作用域的:

          let b = 2;  function foo(b = 3 ,a = b) {     return a; }  foo(); // 3

          給多個(gè)參數(shù)設(shè)置默認(rèn)值,它們會(huì)按順序初始化的,遵循“暫時(shí)性死區(qū)”的規(guī)則,即前面的參數(shù)不能引用后面的參數(shù):

          function foo(a = b, b = 2) {     return a + b; }  foo(); // 報(bào)錯(cuò),b 在初始化之前不能訪(fǎng)問(wèn)

          六、參數(shù)的收集與展開(kāi)

          剩余參數(shù)

          ES6 提供了**剩余參數(shù)(rest)**的語(yǔ)法(...變量名),它可以收集函數(shù)多余的實(shí)參(即沒(méi)有對(duì)應(yīng)形參的實(shí)參),這樣就不再需要使用 arguments 對(duì)象來(lái)獲取了。形參使用了 ... 操作符會(huì)變成一個(gè)數(shù)組,多余的實(shí)參都會(huì)被放進(jìn)這個(gè)數(shù)組中。

          剩余參數(shù)基本用法:

          function sum(a, ...values) {       for (let val of values) {         a += val;     }          return a; }  sum(0, 1, 2, 3); // 6

          上面例子中,在參數(shù)初始化時(shí),首先根據(jù)參數(shù)位置進(jìn)行匹配,把 0 賦值給 a ,然后剩余的參數(shù) 1、2、3 都會(huì)被放進(jìn)數(shù)組 values 中。

          下面是分別用 arguments 對(duì)象和剩余參數(shù)來(lái)獲取參數(shù)的對(duì)比例子:

          // arguments 的寫(xiě)法 function sortNumbers() { 	return Array.prototype.slice.call(arguments).sort(); }  // 剩余參數(shù)的寫(xiě)法 const sortNumbers = (...numbers) => {     return numbers.sort(); }

          可以看出剩余參數(shù)的寫(xiě)法更加簡(jiǎn)潔。盡管 arguments 是一個(gè)類(lèi)數(shù)組,也是可迭代對(duì)象,但它終究不是數(shù)組。它不支持?jǐn)?shù)組方法,當(dāng)我們使用 arguments 時(shí),如果想要調(diào)用數(shù)組方法,就必須使用Array.prototype.slice.call先將其轉(zhuǎn)為數(shù)組。

          而剩余參數(shù)它不同于 arguments 對(duì)象,它是真正的 Array 實(shí)例,能夠很方便地使用數(shù)組方法。并且箭頭函數(shù)也支持剩余參數(shù)。

          另外,使用剩余參數(shù)不會(huì)影響 arguments 對(duì)象的功能,它仍然能夠反映調(diào)用函數(shù)時(shí)傳入的參數(shù)。

          • 剩余參數(shù)的位置

          剩余參數(shù)必須是最后一個(gè)形參,否則會(huì)報(bào)錯(cuò)。

          // 報(bào)錯(cuò) function fn1(a, ...rest, b) { 	console.log([a, b, rest]); }   // 正確寫(xiě)法 function fn2(a, b, ...rest) {     console.log([a, b, rest]); }  fn2(1, 2, 3, 4) // 輸出 [1, 2, [3, 4]]

          展開(kāi)語(yǔ)法

          前面我們知道了如何把多余的參數(shù)收集為一個(gè)數(shù)組,但有時(shí)候我們需要做一些相反的事,例如要把一個(gè)數(shù)組中的元素分別傳入給某個(gè)函數(shù),而不是傳入一個(gè)數(shù)組,像這樣:

          function sum(...values) {     let sum = 0;          for (let val of values) {         sum += val;     }          return sum; }  let arr = [1, 2, 3, 4];  sum(arr); // "01,2,3,4"

          上面例子的函數(shù)會(huì)把所有傳進(jìn)來(lái)的數(shù)值累加,如果直接傳入一個(gè)數(shù)組,就得不到我們想要的結(jié)果。

          例子中傳入一個(gè)數(shù)組, values 的值會(huì)變成 [[1, 2, 3, 4]],導(dǎo)致數(shù)組 values 中只有一個(gè)元素,而這個(gè)元素的類(lèi)型是數(shù)組。那么函數(shù)返回值就是數(shù)值 0 和數(shù)組 [1, 2, 3, 4]相加的結(jié)果了,兩者各自進(jìn)行了類(lèi)型的隱式轉(zhuǎn)換變成字符串,然后再相加,是一個(gè)字符串拼接的效果。

          要實(shí)現(xiàn)把數(shù)組拆解傳入給函數(shù),首先不可能一個(gè)個(gè)傳入?yún)?shù)——sum(arr[0], arr[1], arr[2], arr[3]);,因?yàn)椴皇侨魏螘r(shí)候都知道數(shù)組中有多少個(gè)元素的,而且數(shù)組中可能會(huì)非常多的元素,手動(dòng)傳是不明智的。

          比較可行的是借助 apply() 方法:

          sum.apply(null, arr); // 10

          但這還不是最優(yōu)解,那么重點(diǎn)來(lái)了!

          ES6 新增的**展開(kāi)語(yǔ)法(spread)**可以幫助我們面對(duì)這種情況。它也是使用 ...變量名 的語(yǔ)法,雖然跟剩余參數(shù)語(yǔ)法一樣,但是用途完全相反,它能夠把一個(gè)可迭代對(duì)象拆分成逗號(hào)分隔的參數(shù)序列。

          在函數(shù)調(diào)用時(shí),它的應(yīng)用是這樣子的:

          sum(...arr); // 10  // 相當(dāng)于 sum(1,2,3,4);

          它甚至可以隨意搭配常規(guī)值使用,沒(méi)有前后位置限制,還可以同時(shí)傳入多個(gè)可迭代對(duì)象:

          sum(-1, ...arr); // 9 sum(...arr, 5); // 15 sum(-1, ...arr, 5); // 14 sum(-1, ...arr, ...[5, 6, 7]); // 27

          展開(kāi)操作符 ... 相當(dāng)于替我們完成了手動(dòng)分別傳參的操作,函數(shù)只知道接收的實(shí)參是單獨(dú)的一個(gè)個(gè)值,不會(huì)因?yàn)檎归_(kāi)操作符的存在而產(chǎn)生其他影響。

          上面的示例雖然都是針對(duì)于數(shù)組的,但展開(kāi)語(yǔ)法能做的還不止這些,其他可迭代對(duì)象例如字符串、字面量對(duì)象都可以展開(kāi),深入了解請(qǐng)參見(jiàn) → 展開(kāi)語(yǔ)法

          總結(jié)

          • 形參是函數(shù)中已聲明的局部變量,傳遞給函數(shù)的實(shí)參會(huì)被賦值給形參,函數(shù)參數(shù)傳遞實(shí)際上是一個(gè)隱式的賦值過(guò)程。

          • 形參和實(shí)參的數(shù)量可以不相等:

            ● 缺失實(shí)參的形參會(huì)得到默認(rèn)值 undefined。

            ● 額外的實(shí)參,可以通過(guò) arguments 對(duì)象訪(fǎng)問(wèn),箭頭函數(shù)除外。

          • 可以通過(guò)傳入對(duì)象的方式讓傳參順序不再重要,讓對(duì)象中的屬性作為真正的實(shí)參。

          • ES6 的參數(shù)默認(rèn)值——函數(shù)調(diào)用時(shí)參數(shù)的值缺失或者是 undefined ,才會(huì)獲取默認(rèn)值。

            ● 設(shè)置默認(rèn)值的形參只有放在最后一位才可以省略傳參。

            ● 形參設(shè)置默認(rèn)值不能引用函數(shù)體中的變量,但可以引用前面的形參和外部變量。

            ● 通過(guò) Object.assign() 或者解構(gòu)賦值實(shí)現(xiàn)默認(rèn)值,能讓傳參的方式更加靈活。

          • 剩余參數(shù)和 arguments 的主要區(qū)別:

            ● 剩余參數(shù)只包含那些沒(méi)有對(duì)應(yīng)形參的實(shí)參,而 arguments 對(duì)象包含了傳給函數(shù)的所有實(shí)參。

            ● 剩余參數(shù)是真正的 Array 實(shí)例,而 arguments 只是類(lèi)數(shù)組對(duì)象。

          • 剩余參數(shù)和展開(kāi)語(yǔ)法都采用 ... 操作符,在函數(shù)的相關(guān)場(chǎng)景中:

            ● 出現(xiàn)在函數(shù)形參列表的最后,它是剩余參數(shù)。

            ● 出現(xiàn)在函數(shù)調(diào)用時(shí),它是展開(kāi)語(yǔ)法。

          贊(0)
          分享到: 更多 (0)
          網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)