js6的未來(二)函數(shù)增強(qiáng)-創(chuàng)新互聯(lián)

js6的未來(二)函數(shù)增強(qiáng)

函數(shù)聲明中的解構(gòu)

JavaScript 的新解構(gòu)賦值得名于數(shù)組或?qū)ο罂梢?“解構(gòu)” 并提取出組成部分的概念。在 第 1 部分 中,學(xué)習(xí)了如何在局部變量中使用解構(gòu)。它在函數(shù)參數(shù)聲明中也很有用。

創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括賈汪網(wǎng)站建設(shè)、賈汪網(wǎng)站制作、賈汪網(wǎng)頁制作以及賈汪網(wǎng)絡(luò)營(yíng)銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,賈汪網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到賈汪省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

如果某個(gè)函數(shù)需要一個(gè)對(duì)象,可以在函數(shù)開始之前,利用解構(gòu)功能提取出該對(duì)象的相關(guān)部分??赏ㄟ^向函數(shù)的參數(shù)添加解構(gòu)語法來實(shí)現(xiàn)此目的,

1. 函數(shù)聲明中的解構(gòu)

let person = {
      firstName: "Ted",
      lastName: "Neward",
      age: 45,
      favoriteLanguages: [
        "ECMAScript", "Java", "C#", "Scala", "F#"
      ]
    }
    function displayDetails({firstName, age}) {
      console.log(`${firstName} is ${age} years old`);
    }
    displayDetails(person);

displayDetails 函數(shù)僅關(guān)心傳入的對(duì)象的 firstName 和 age 字段。向?qū)ο笳Z法添加一個(gè)解構(gòu)賦值,可在函數(shù)調(diào)用中有效地提取出這些值。調(diào)用語法本身保持不變,重構(gòu)遺留代碼來使用新語法變得更容易。
也可以在函數(shù)中使用解構(gòu)數(shù)組語法,但它沒有您即將看到的其他一些功能那么令人印象深刻。

函數(shù)參數(shù)

ECMAScript 對(duì)函數(shù)參數(shù)執(zhí)行了語法改動(dòng)。為函數(shù)調(diào)用引入了默認(rèn)參數(shù)值、剩余參數(shù)和展開運(yùn)算符,
首先將介紹默認(rèn)參數(shù),這可能是 3 個(gè)概念中最容易理解的概念。

2. 默認(rèn)參數(shù)

let sayHello = function(message = "Hello world!") {
  console.log(message);
}
sayHello();         // prints "Hello world!"
sayHello("Howdy!"); // prints "Howdy!"

基本上講:在調(diào)用位置指定了一個(gè)參數(shù),那么該參數(shù)將接受傳遞的值;未指定值,則會(huì)分配默認(rèn)值。
與 第 1 部分 中介紹的一些更新一樣,新的默認(rèn)參數(shù)實(shí)質(zhì)上就是語法糖。以前的 ECMAScript 版本中,

3. 舊式默認(rèn)參數(shù)

var sayHello = function(message) {
  if (message === undefined) {
    message = "Hello world!";
  }
  console.log(message);
}
sayHello();         // prints "Hello world!"
sayHello("Howdy!"); // prints "Howdy!"

剩余參數(shù)(Rest parameters)

ECMAScript 庫中的一種更常見的做法是,定義函數(shù)或方法來接受一個(gè)或多個(gè)固定參數(shù),后跟一組通過用戶定義方式細(xì)化或修改調(diào)用的可選參數(shù)。在過去,可以通過訪問靜默構(gòu)建并傳遞給每個(gè)函數(shù)調(diào)用的內(nèi)置 arguments 參數(shù)來實(shí)現(xiàn)此目的:

4. 舊式可選參數(shù)

function greet(firstName) {
  var args = Array.prototype.slice.call(arguments, greet.length);
  console.log("Hello",firstName);
  if (args !== undefined)
    args.forEach(function(arg) { console.log(arg); });
}
greet("Ted");
greet("Ted", "Hope", "you", "like", "this!");

5. 剩余參數(shù)

function greet(firstName, ...args) {
 console.log("Hello",firstName);
 args.forEach(function(arg) { console.log(arg); });
}
greet("Ted");
greet("Ted", "Hope", "you", "like", "this!");

注意,剩余參數(shù)(第一個(gè)清單中的 args)不需要測(cè)試存在與否;該語言可確保它將以長(zhǎng)度為 0 的數(shù)組形式存在,即使沒有傳遞其他參數(shù)。

展開運(yùn)算符

展開運(yùn)算符(Spread operator)在某些方面與剩余參數(shù)的概念正好相反。剩余參數(shù)將會(huì)收集傳入某個(gè)給定調(diào)用的一些可選值,展開運(yùn)算符獲取一個(gè)值數(shù)組并 “展開” 它們,基本上講,就是解構(gòu)它們以用作被調(diào)用的函數(shù)的各個(gè)參數(shù)。
展開運(yùn)算符的最簡(jiǎn)單用例是將各個(gè)元素串聯(lián)到一個(gè)數(shù)組中:

6. 使用展開運(yùn)算符進(jìn)行串聯(lián)

let arr1 = [0, 1, 2];
let arr2 = [...arr1, 3, 4, 5];
console.log(arr2); // prints 0,1,2,3,4,5

沒有展開運(yùn)算符語法,需要提取第一個(gè)數(shù)組中的每個(gè)元素并附加到第二個(gè)數(shù)組,然后才添加剩余元素。
也可以在函數(shù)調(diào)用中使用展開運(yùn)算符;事實(shí)上,這是您最有可能使用它的地方:

7. 函數(shù)調(diào)用中的展開運(yùn)算符

function printPerson(first, last, age) {
 console.log(first, last age);
}
let args = ["Ted", "Neward", 45];
printPerson(...args);

注意,不同于剩余參數(shù),展開運(yùn)算符是在調(diào)用點(diǎn)上使用,而不是在函數(shù)定義中使用。

函數(shù)語法和語義

本節(jié)將介紹最重要的更新。只需記住,JavaScript 程序中的原始語法仍然可行。

箭頭函數(shù)

箭頭函數(shù)語法,這是一種用于創(chuàng)建函數(shù)字面量的速記符號(hào)。從 ECMAScript 6 開始,可以使用所謂的粗箭頭(與細(xì)箭頭相對(duì))創(chuàng)建函數(shù)字面量,就像這樣:

8. 創(chuàng)建函數(shù)字面量的箭頭語法

let names = ["Ted","Jenni","Athen"];
names.forEach((n) => console.log(n));

箭頭函數(shù)也很容易理解:箭頭前的括號(hào)將參數(shù)捕獲到函數(shù)主體,箭頭本身表示函數(shù)主題的開頭。如果主體僅包含一條語句或表達(dá)式,則不需要使用花括號(hào)。如果主體包含多條語句或表達(dá)式,那么可以通過在箭頭后輸入花括號(hào)來表示它們:

9. 表示多條語句或表達(dá)式

let names = ["Ted","Jenni","Athen"];
names.forEach((n) => {
   console.log(n)
});

如果只有一個(gè)參數(shù),您可以選擇完全省略括號(hào),

10. 單個(gè)參數(shù)

names.forEach(n => console.log(n));

注意,箭頭函數(shù)的主體是只有一個(gè)值的單個(gè)表達(dá)式,則無需顯式返回,而是應(yīng)該將單一表達(dá)式隱式返回給箭頭函數(shù)的調(diào)用方。但是,如果主體不只一條語句或表達(dá)式,則必須使用花括號(hào),而且所有返回的值都必須通過常用的 “return” 語法發(fā)回給調(diào)用方。

箭頭函數(shù)不能直接取代函數(shù)關(guān)鍵字。一般而言,您應(yīng)該繼續(xù)使用 function 定義方法(即與一個(gè)對(duì)象實(shí)例關(guān)聯(lián)的函數(shù))。為對(duì)象無關(guān)的場(chǎng)景保留箭頭函數(shù),比如 Array.forEach 或 Array.map 調(diào)用的主體。因?yàn)榧^函數(shù)對(duì)待 this 的方式與普通函數(shù)不同,所以在方法定義中使用它們可能導(dǎo)致意料之外的結(jié)果。

‘this’ 的新定義

this 參數(shù)引用的對(duì)象上會(huì)調(diào)用一個(gè)方法,如下所示:

11. ‘this’ 引用一個(gè)對(duì)象實(shí)例

let bob = {
  firstName: "Bob",
  lastName: "Robertson",
  displayMe: function() {
    for (let m in this) {
      console.log(m,"=",this[m]);
    }
  }
};
bob.displayMe();

上面的參數(shù)顯然引用了實(shí)例 bob,而且忠實(shí)地打印出 firstName、lastName 和 displayMe 方法(因?yàn)樗彩窃搶?duì)象的成員)的名稱和值。

當(dāng)從一個(gè)存在于全局范圍的函數(shù)引用 this 時(shí),情況會(huì)變得有點(diǎn)怪異:

12. ‘this’ 引用一個(gè)全局范圍對(duì)象

let displayThis = function() {
  for (let m in this) {
    console.log(m);
  }
};
displayThis()

ECMAScript 將全局范圍定義為一個(gè)對(duì)象,所以當(dāng)在全局范圍內(nèi)的函數(shù)使用時(shí),this 引用全局范圍對(duì)象,在上面的情況中,它忠實(shí)地打印出全局范圍的每個(gè)成員,包括頂級(jí)全局變量、函數(shù)和對(duì)象(比如上面的示例中的 “console”)。

出于這個(gè)原因,我們也可以在兩種不同的上下文中重用該函數(shù),知道它每次將或多或少執(zhí)行一些我們期望的操作:

13. 重用全局范圍函數(shù)

let displayThis = function() {
  for (let m in this) {
    console.log(m);
  }
};
displayThis(); // this == global object
let bob = {
  firstName: "Bob",
  lastName: "Robertson",
  displayMe: displayThis
};
bob.displayMe(); // this == bob

可能此語法有點(diǎn)奇怪,但只要您理解了規(guī)則,就不是問題。直到您嘗試使用 ECMAScript 構(gòu)造函數(shù)作為對(duì)象類型時(shí),情況才會(huì)真正偏離主題:

14. 一個(gè)過度使用的 ‘this’

function Person() {
  // The Person() constructor defines "this" as an instance
  // of itself
  this.age = 0;

  setInterval(function growUp() {
    // In non-strict mode, the growUp() function defines "this"
    // as the global object; thus, "this.age" refers to a global
    // "age" value, not the one defined on the instance of Person
    this.age++;
  }, 1000);
}
var p = new Person();
// Every second, p.age is supposed to go up by one.
// But because the "this" in the "growUp" function literal
// refers to the global object, and not "p", p.age will
// never change from 0.

詞法 ‘this’ 綁定

為了解決與 this 相關(guān)的定義問題,箭頭函數(shù)擁有所謂的詞法 this 綁定。這意味著箭頭函數(shù)在定義函數(shù)時(shí)使用 this 值,而不是在執(zhí)行它時(shí)。
采用規(guī)則:完全理解新 this 規(guī)則可能需要一段時(shí)間。新箭頭函數(shù)規(guī)則并不總是這么直觀。作為開發(fā)人員,可以計(jì)劃對(duì) “內(nèi)聯(lián)” 函數(shù)使用箭頭函數(shù),對(duì)方法使用傳統(tǒng)函數(shù)。如果這么做,各個(gè)方面都應(yīng)按預(yù)期工作。
或許理解這一區(qū)別的最簡(jiǎn)單方法是借助一個(gè)舊的 Node.js 對(duì)象 EventEmitter?;叵胍幌拢珽ventEmitter(獲取自 events 模塊)是一個(gè)簡(jiǎn)單的發(fā)布-訂閱式消息系統(tǒng):您可以在某個(gè)特定事件名稱上的發(fā)射器上注冊(cè)回調(diào),當(dāng)該事件被 “發(fā)出” 時(shí),則按注冊(cè)的順序觸發(fā)回調(diào)。
如果向 EventEmitter 注冊(cè)一個(gè)遺留函數(shù),捕獲的 this 將是在運(yùn)行時(shí)確定的參數(shù)。但是如果您向 EventEmitter 注冊(cè)一個(gè)箭頭函數(shù),this 將在定義箭頭函數(shù)時(shí)綁定:

15. ‘this’ 被箭頭函數(shù)綁定

let EventEmitter = require('events');
let ee = new EventEmitter();
ee.on('event', function() {
 console.log("function event fired", this);
});
ee.on('event', () => {
 console.log("arrow event fired", this);
});
var bob = {
 firstName: "Bob",
 lastName: "Robertson"
};
bob.handleEventLegacy = function() {
 console.log("function event fired", this);
};
bob.handleEventArrow = () => {
 console.log("arrow event fired", this);
};
ee.on('event', bob.handleEventLegacy);
ee.on('event', bob.handleEventArrow);
ee.emit('event');

在觸發(fā)函數(shù)事件時(shí),this 被綁定到 EventEmitter 本身,而箭頭事件未綁定到任何目標(biāo)(它們分別打印一個(gè)空對(duì)象)。

生成器函數(shù)

生成器函數(shù)旨在生成一個(gè)值流供其他方使用。許多函數(shù)語言都使用了生成器,它們?cè)谄渲锌赡苊麨榱?nbsp;或序列?,F(xiàn)在 ECMAScript 中也引入了它們。
要了解生成器的實(shí)際工作原理,需要稍作解釋。首先,想象一組簡(jiǎn)單的名稱:

16. 一個(gè)簡(jiǎn)單的集合

var names = ["Ted", "Charlotte", "Michael", "Matthew"];

17. 一個(gè)返回每個(gè)名稱的函數(shù)

var getName = (function() {
  var current = 0;
  return function() {
    if (current > names.length)
      return undefined;
    else {
      var temp = names[current];
      current++;
      return temp;
    }
  };
})();
console.log(getName()); // prints Ted
console.log(getName()); // prints Charlotte
console.log(getName()); // prints Michael
console.log(getName()); // prints Matthew
console.log(getName()); // prints undefined

起初,上面的函數(shù)返回函數(shù)的方式可能看起來很陌生。這是必要的,因?yàn)?nbsp;getName 函數(shù)需要在多個(gè)函數(shù)調(diào)用中跟蹤它的狀態(tài)。在類似 C 的語言中,可以將狀態(tài)存儲(chǔ)在getName 函數(shù)內(nèi)的靜態(tài)變量中,但像類似的 Java 和 C# 一樣,ECMAScript 不支持在函數(shù)中使用靜態(tài)變量。在這種情況下,我們將使用閉包,以便函數(shù)字面量在返回后繼續(xù)綁定到 “當(dāng)前” 變量,使用該變量存儲(chǔ)自己的狀態(tài)。
要理解的重要一點(diǎn)是,此函數(shù)不會(huì)一次獲取一個(gè)有限的值序列(采用返回?cái)?shù)組的形式),它一次獲取一個(gè)元素,直到?jīng)]有剩余的元素。
但是如果要返回的元素永遠(yuǎn)用不完,該怎么辦?

函數(shù)編程中的無限流

18. 一個(gè)有限的流

var getName = (function() {
  var current = 0;
  return function() {
    switch (current++) {
      case 0: return "Ted";
      case 1: return "Charlotte";
      case 2: return "Michael";
      case 3: return "Matthew";
      default: return undefined;
    }
  };
})();<< span="">

從技術(shù)上講,您看到的仍是一個(gè)迭代器,但它的實(shí)現(xiàn)看起來與來自樣本的迭代器截然不同;這里沒有集合,只有一組硬編碼的值。
從本質(zhì)上講,它是一個(gè)沒有關(guān)聯(lián)集合的迭代器,這突出了一個(gè)重要的事實(shí):我們的函數(shù)生成的值的來源 現(xiàn)在深度封裝在離調(diào)用方很遠(yuǎn)的地方。這進(jìn)而引入了一個(gè)更有趣的想法:調(diào)用方可能不知道最初沒有集合,不知道生成的值永無止境。這就是一些語言所稱的無限流。
斐波納契數(shù)列(全球每種函數(shù)語言的 “Hello World” 等效程序)就是這樣一個(gè)無限流:

19. 斐波納契數(shù)的無限流

var fibo = (function() {
  var prev1 = undefined;
  var prev2 = undefined;
  return function() {
    if (prev1 == undefined && prev2 == undefined) {
      prev1 = 0;
      return 0;
    }
    if (prev1 == 0 && prev2 == undefined) {
      prev1 = 1;
      prev2 = 0;
      return 1;
    }
    else {
      var ret = prev1 + prev2;
      prev2 = prev1;
      prev1 = ret;
      return ret;
    }
  };
})();

無限流 是一個(gè)從不會(huì)用完要返回的值的流。在這種情況下,斐波拉契數(shù)列沒有邏輯終點(diǎn)。
JavaScript 中的反應(yīng)式編程非常復(fù)雜。如果您打算了解更多的信息,可以訪問 JavaScript 反應(yīng)式編程 GitHub 頁面。
盡管起初看起來很奇怪,但無限流的概念是其他一些基于 ECMAScript 的有趣技術(shù)(比如反應(yīng)式編程)的核心。想想如果我們將用戶事件(比如移動(dòng)鼠標(biāo)、單擊按鈕和按鍵)視為無限流,函數(shù)從流中獲取每個(gè)事件并進(jìn)行處理,結(jié)果會(huì)怎樣?
構(gòu)建無限流所需的代碼量非常大,所以 ECMAScript 6 定義了一種新語法(和一個(gè)新關(guān)鍵字)來讓代碼更加簡(jiǎn)潔。在這里可以看到,我重寫了清單 17 中的示例:

20. 一個(gè)使用生成器的有限值流

function* getName() {
  yield "Ted";
  yield "Charlotte";
  yield "Michael";
  yield "Matthew";
}
let names = getName();
console.log(names.next().value);
console.log(names.next().value);
console.log(names.next().value);
console.log(names.next().value);
console.log(names.next().value);

同樣地,該函數(shù)將按順序打印出每個(gè)名稱。當(dāng)它用完所有名稱時(shí),它會(huì)不停地打印 “undefined”。在語法上,yield 關(guān)鍵字看起來類似于 return,但事實(shí)上,它表示 “返回但記住我在此函數(shù)中的位置,以便下次調(diào)用它時(shí),從離開的位置開始執(zhí)行?!边@顯然比傳統(tǒng)的 return 更復(fù)雜。
生成器的使用與第一個(gè)示例稍微不同:我們捕獲了 getName 函數(shù)的返回值,然后像迭代器一樣使用該對(duì)象。這是 ECMAScript 6 中的一個(gè)特意的設(shè)計(jì)決定。從技術(shù)上講,生成器函數(shù)返回一個(gè) Generator 對(duì)象,該對(duì)象用于從生成器函數(shù)獲取各個(gè)值。新語法旨在盡可能地模擬迭代器。
談到迭代器,還有最后一個(gè)需要知道的語法更改。

for-of 關(guān)鍵字

經(jīng)典的 for 循環(huán)在 ECMAScript 6 具有了新形式,這是由于添加了一個(gè)輔助關(guān)鍵字:of。在許多方面,新語法與 for-in 沒多大區(qū)別,但它支持生成器函數(shù)。
返回到清單 19 中的斐波納契數(shù)列,這是向函數(shù)添加 for-of 關(guān)鍵字時(shí)發(fā)生的情況:

21. 斐波納契數(shù)列中的 ‘for of’

function* fibo() { // a generator function
  yield 0;
  yield 1;
  let [prev, curr] = [0, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (let n of fibonacci()) {
  console.log(n);

  // By the way, this is an infinite stream, so this loop
  // will never terminate unless you break out of it
}

for-of 和 for-in 之間存在著細(xì)微區(qū)別,但在大多數(shù)情況下,您可以使用 for-of 直接取代舊語法。它添加了隱式使用生成器的能力 — 就像我們?cè)跓o限流示例中使用 getName() 執(zhí)行的操作一樣。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

當(dāng)前題目:js6的未來(二)函數(shù)增強(qiáng)-創(chuàng)新互聯(lián)
文章鏈接:http://muchs.cn/article4/ceepie.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供營(yíng)銷型網(wǎng)站建設(shè)面包屑導(dǎo)航、外貿(mào)網(wǎng)站建設(shè)網(wǎng)站導(dǎo)航、網(wǎng)站設(shè)計(jì)品牌網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都app開發(fā)公司