1. 程式人生 > 其它 >[ES6深度解析]9:Rest引數和預設值

[ES6深度解析]9:Rest引數和預設值

Rest引數

在建立API時,一個常見的需求是建立可變引數函式(引數個數不確定),這個函式可以接受任意數量的引數。例如,string.prototype.concat方法接受任意數量的字串引數。通過使用rest引數,ES6提供了一種編寫可變引數函式的新方法。

為了演示,讓我們編寫一個簡單的可變引數函式containsAll,它檢查一個字串是否包含許多子字串。例如,containsAll("banana","b","nan")將返回true,而containsAll("banana","c","nan")將返回false

下面是實現這個函式的傳統方法:

function containsAll(haystack) {
  for (var i = 1; i < arguments.length; i++) {
    var needle = arguments[i];
    if (haystack.indexOf(needle) === -1) {
      return false;
    }
  }
  return true;
}

這個實現使用了神奇的arguments物件,這是一個包含傳遞給函式的形參的類陣列物件。這段程式碼當然做了我們想要的,但是它的可讀性不是最佳的。函式形參列表只包含一個形參haystack,所以不可能一眼就看出函式實際上有多個實參。此外,我們必須小心地開始遍歷arguments 索引為1而不是0的引數,因為arguments[0] 對應於haystack引數。如果我們想在haystack之前或之後新增另一個引數,我們必須記住更新for迴圈。Rest引數解決了這兩個問題。下面是一個使用rest引數的containsAll的自然ES6實現:

function containsAll(haystack, ...needles) {
  for (var needle of needles) {
    if (haystack.indexOf(needle) === -1) {
      return false;
    }
  }
  return true;
}

這個版本的函式具有與第一個相同的行為,但包含特殊的...needles語法。讓我們看看呼叫containsAll("banana","b","nan")時如何呼叫這個特殊語法。引數haystack像往常一樣被首先傳遞的引數賦值,即banananeedles前的省略號...表示它是一個rest引數。所有其他傳遞的引數都放在一個數組中,並賦值給變數needles。對於我們的示例呼叫,needles設定為[“b”,“nan”]。然後函式繼續正常執行。

只有函式的最後一個引數才可以標記為rest引數。在呼叫中,rest引數之前的引數照常賦值。任何“額外”引數被放入一個數組中,並賦值給rest引數。如果沒有額外的引數,那麼rest形參將只是一個空陣列;rest引數永遠不會是undefined

預設引數(Default parameters)

通常,函式不需要呼叫者傳遞所有可能的引數,對於未傳遞的引數,可以使用合理的預設值。JavaScript總是有一種不靈活的預設引數形式;未傳遞值的引數預設為undefined。ES6引入了一種指定任意引數預設值的方法。這是一個例子:

function animalSentence(animals2="tigers", animals3="bears") {
    return `Lions and ${animals2} and ${animals3}! Oh my!`;
}

對於每個引數,=後面的部分是一個表示式,如果呼叫者沒有傳遞引數,則指定引數的預設值。因此,animalSentence() 返回"Lions and tigers and bears! Oh my!";animalSentence("elephants") 返回"Lions and elephants and bears! Oh my!";animalSentence("elephants", "whales") 返回"Lions and elephants and whales! Oh my!";

以下是與預設引數相關的一些微妙之處:

  • 與Python不同,預設值表示式在函式呼叫時從左到右計算求值。這也意味著預設值表示式可以使用在它之前(左側)填充的引數的值。例如,我們可以讓我們的動物句子功能更奇妙,如下所示:
function animalSentenceFancy(animals2="tigers", animals3=(animals2 == "bears") ? "sealions" : "bears")
{
  return `Lions and ${animals2} and ${animals3}! Oh my!`;
}
// animalSentenceFancy("bears") 返回 "Lions and bears and sealions. Oh my!"
  • 傳遞undefined被認為等於什麼都不傳遞。因此,animalSentence(undefined, "unicorns")返回"Lions and tigers and unicorns! Oh my!"
  • 沒有預設值的形參隱式預設為undefined。 function myFunc(a=42, b) {...}是允許的,等同於function myFunc(a=42, b=undefined) {...}

拋棄arguments

現在我們已經看到,rest形參和預設值可以替代arguments物件的使用,刪除arguments通常會使程式碼更易於閱讀。除了有損可讀性之外,arguments物件的魔力還會給優化JavaScript vm帶來麻煩。

本文來自部落格園,作者:Max力出奇跡,轉載請註明原文連結:https://www.cnblogs.com/welody/p/15180100.html

如果覺得文章不錯,歡迎點選推薦