iT邦幫忙

2021 iThome 鐵人賽

DAY 14
0
Modern Web

追求JS小姊姊30天系列 第 14

追求JS小姊姊系列 Day14 -- 方函式的能力展現:認識生成器,工具人更神氣(上)

前情提要

方函式準備展示第二個型態

:有些情境下,時間就是不能掌握,這要求也太誇張了。
方函式:很不合理吧,連一個女生都沒辦法掌握了,何況是時間呢?

方函式:但身為頭等工具人就是要能應對各種不合理
生成器型態就可用於應付所謂時間不平等的情境

(說完發現方函式拿出了像是遙控器的物件)


生成器模式登場

:第二型態能力是用... 遙控器控制你以為在演王牌天神?
方函式你懂生成器,生成器就會幫你,為了幫助你追到JS,我會告訴你,包含:

  1. 生成器的創建
  2. 生成器與一般函式的差異
  3. 生成器內的內容
  4. 生成器的使用方式
  5. 簡易案例

:為何要幫我!?(工具人當到瘋了嗎?)


生成器的介紹方式:

  1. 創造方式: 新增*關鍵字放於function後方
function* generator(i){
    yield 1;
    yield* 2;
    return 3;
}
  1. yield,yield*是什麼
    yield
    生成器內的值是透過yield語句(中文翻譯為產出),但實際上我們不只能藉由它傳出(output)值,也能做到傳入(input)值、甚至是拋出(throw)值
    yield*:
    可以將原本生成器的yield*後的內容交由另一個生成器去進行執行
//產生一個生成器
function* generator(i){
    console.log("我會被執行嗎?");
    yield "test";
}

生成器跟一般函式的差異

  1. 呼叫
    下圖分別是生成器generator()跟一般函式normalFn()
//生成器
function* generator(i){
    console.log("我會被執行嗎?");
    yield 1;
    
}

//一般的函式 
function normalFn(i){
    console.log("我會被執行");
}

console.log(generator(1));
console.log(normalFn(1));

一般函式normalFn():你呼叫後會直接執行函式內的內容。
生成器:呼叫generator()只得到了undefined

(上圖為:generator()normalFn()的執行結果)

那生成器的定位是什麼?來看看MDN怎麼說:

Calling a generator function does not execute its body immediately; an iterator object for the function is returned instead

大意是:呼叫生成器本身並不會回傳內容,而是會產生一個迭代器

方函式:就是透過我手上的這個東西。

生成器專屬的遙控器 -- iterator object

製作方法:把生成器呼叫存入變數,這個動作背後的意義是:
產生一個用於控制生成器的操作器(iterator)

遙控器的使用方法next()
會回傳一個物件 {value:,done:},以下進行解釋:

  1. value: yield後的值
  2. done:會有兩種情形(true/false)

done顯示為false:代表生成器的內容還沒執行完


//生成器
function* generator(i){
    yield 1;
}

//產生遙控器
let control =generator();

//開始操作
console.log(control.next(),"我是結果");

done顯示為true:代表生成器的內容已經執行完

function* generator(i){
    yield 1;
}

//產生遙控器
let control =generator();

//開始操作
console.log(control.next(),"我是第一次執行");
console.log(control.next(),"希望這次看得到`true`");


基本略知、也會操作,那來看看傳值吧

方函式:我們已知可藉由yield傳出(output)值,那還記得之前提到:
它也能做到傳入(input)值、甚至是拋出(throw)值 這件事嗎?現在來試試看吧?

傳入(input)值

  1. 建立迭代器時,同時將值傳入參數:
function* generator(i){
    yield i;
}

//在這傳入
let control =generator(123);

//開始操作
console.log(control.next(),"得到傳入的值");
  1. next()方法傳入:
    先知道:
    1. 這會讓生成器的狀態: 待命中/暫停生產 > 執行中
    2. 透過next方法傳入的值,會被提供給暫停中的yield內容,什麼意思呢?

首次用呼叫生成器

function* generator(i){
    yield i;
    yield i;
}
const controls = generator();

//嘗試在第一次next()傳入值
let call1 = controls.next(5);
console.log(call1);

我們無法在第一次使用next方法就提供,若要第一次傳入值,只能透過建立迭代器時傳入,至於背後原因之後再說。

  1. throw()方法傳入:
    我們可運用它將異常內容拋給生成器
注意:要先將生成器狀態啟動(解除待命中),才能使用拋出
function* generator(i){
    try{
        yield i;
    }catch(error){
        console.log(error,"yes,catch error!");
    }
}

//在這傳入
let control =generator();
let x = control.next();
control.throw("can you throw?");

//開始操作

方函式:看到那麼多的名詞,什麼暫停、啟動狀態,你是不是也該好奇生成器背後的原理呢?
:不,我只想休息...

-- to be continued --


那今天就到這邊摟!今天分享喜歡的歌是:
That's Life (Remastered 2008)
https://www.youtube.com/watch?v=TnlPtaPxXfc

每天的休息,是為了後面的追求,明天見。


reference:

JavaScript — from callbacks to async/await
忍者2
22. Generators
function*


上一篇
追求JS小姊姊系列 Day13 -- 方函式的能力展現:懂回呼函式才能當好工具人
下一篇
追求JS小姊姊系列 Day15 -- 方函式的能力展現:認識生成器,工具人更神氣(下)
系列文
追求JS小姊姊30天30

1 則留言

1
Chiahsuan
iT邦新手 4 級 ‧ 2021-09-29 16:00:15

越來越佩服你的創意了!!!/images/emoticon/emoticon32.gif

希望口味還讓小書蟲滿意

我要留言

立即登入留言