摘要:始最近的業(yè)余時間在看相關(guān)的書也在極客時間上買了前端相關(guān)的專欄對于一個非的人來說時時會有一種感覺社區(qū)是真的激進(jìn)和浮燥這幫規(guī)則的制定者似乎從來也不知道克制為何物有很多時候固有的東西是可以處理好的但是偏偏喜歡人為制造一些概念和語法糖人為的建起一座
始
最近的業(yè)余時間在看 js 相關(guān)的書, 也在極客時間上買了前端相關(guān)的專欄, 對于一個非 jser 的人來說, 時時會有一種感覺: js 社區(qū)是真的激進(jìn)和浮燥, 這幫規(guī)則的制定者似乎從來也不知道克制為何物. 有很多時候固有的東西是可以處理好的, 但是偏偏喜歡人為制造一些概念和語法糖, 人為的建起一座又一座的高山, 似乎你沒跨過就是個 "菜雞"
請?jiān)徫业膼憾? 看《js 語言精粹》的時候, 這種感覺非常的強(qiáng)烈. 作者是業(yè)內(nèi)的大牛, 還制定了 json, 但是每一章還在最開頭引一句莎翁的話, "似乎無關(guān)緊要又暗藏哲理". 書中很多內(nèi)容要表達(dá)的意思總有一種: 明明可以將話說成 10 分讓一個普通人都能看得明白的, 卻偏不, 只說 6 分, 剩下的自己去悟, 有很多規(guī)則性的東西并非是靠悟, 而是靠幾句話說清楚其本質(zhì)就豁然開朗的.
換成以前, 會覺得這人是一座好大的高山要進(jìn)行膜拜, 這幾年雖然自己技術(shù)依然不那么好, 但是還是喜歡去思考一些內(nèi)在的東西, 更在努力一點(diǎn)一點(diǎn)把心里的權(quán)威崇拜給去掉, 再看到這些的時候, "..." 這幾個標(biāo)點(diǎn)符號很容易印在腦子里. 感覺這不只是一兩個人這樣, 極有可能是整個 js 圈子都是這樣
說回標(biāo)題上來, 除了看書, 看專欄, 找資料, 很久都還是沒有把 generator 和 async/await 給理解透, 于是自己試著整個梳理了一下運(yùn)行的流程
Generator我先試著在 yield 后面不跟任何的東西, 可以直接復(fù)制到控制臺輸出
function *f0(param) { console.log("n: " + param); yield; console.log("i"); let l = yield; console.log("l: " + l); } let v0 = f0("p"); console.log(v0.next(1)); // 輸出 n: p 和 {value: undefined, done: false} console.log("----"); console.log(v0.next(2)); // 輸出 i 和 {value: undefined, done: false} console.log("----"); console.log(v0.next(3)); // 輸出 l: 3 和 {value: undefined, done: true} console.log("----"); console.log(v0.next(4)); // 輸出 {value: undefined, done: true} console.log("----"); console.log(v0.next(5)); // 輸出 {value: undefined, done: true}
在上面的基礎(chǔ)上給方法 return 值
function *f1() { console.log("n"); yield; console.log("i"); let l = yield; console.log("l: " + l); return "?"; } let v1 = f1(); console.log(v1.next(1)); // 輸出 n 和 {value: undefined, done: false} console.log("----"); console.log(v1.next(11)); // 輸出 i 和 {value: undefined, done: false} console.log("----"); console.log(v1.next(111)); // 輸出 l: 111 和 {value: "?", done: true} console.log("----"); console.log(v1.next(1111)); // 輸出 {value: undefined, done: true} console.log("----"); console.log(v1.next(11111)); // 輸出 {value: undefined, done: true}
然后我試著在 yield 的后面加上內(nèi)容
function *f2(param) { console.log("0: " + param); let f = yield 1; console.log("1: " + f); let s = yield f + 2; console.log("2: " + s); let t = yield (s + 3); console.log("3: " + t); let fo = (yield s) + 4; console.log("4: " + fo); } let v2 = f2("p"); console.log(v2.next("N")); // 輸出 0: p 和 {value: 1, done: false} console.log("----"); console.log(v2.next("I")); // 輸出 1: I 和 {value: "I2", done: false} console.log("----"); console.log(v2.next("L")); // 輸出 2: L 和 {value: "L3", done: false} console.log("----"); console.log(v2.next("S")); // 輸出 3: S 和 {value: "L", done: false} console.log("----"); console.log(v2.next("H")); // 輸出 4: H4 和 {value: undefined, done: true} console.log("----"); console.log(v2.next("I")); // 輸出 {value: undefined, done: true} console.log("----"); console.log(v2.next("T")); // 輸出 {value: undefined, done: true}
最后, 在上面的基礎(chǔ)上給方法 return 值
function *f3() { console.log("0"); let y1 = yield 1; console.log("1: " + y1); let y2 = yield y1 + 2; console.log("2: " + y2); let y3 = yield (y2 + 3); console.log("3: " + y3); let y4 = (yield y3) + 4; console.log("4: " + y4); return "??"; } let v3 = f3(); console.log(v3.next("N")); // 輸出 0 和 {value: 1, done: false} console.log("----"); console.log(v3.next("I")); // 輸出 1: I 和 {value: "I2", done: false} console.log("----"); console.log(v3.next("L")); // 輸出 2: L 和 {value: "L3", done: false} console.log("----"); console.log(v3.next("S")); // 輸出 3: S 和 {value: "S", done: false} console.log("----"); console.log(v3.next("H")); // 輸出 4: H4 和 {value: "??", done: true} console.log("----"); console.log(v3.next("I")); // 輸出 {value: undefined, done: true} console.log("----"); console.log(v3.next("T")); // 輸出 {value: undefined, done: true}
大致上就清楚 yield 的運(yùn)行邏輯了, 以上面的 f3 為例, 對照上面的輸出來看, 它其實(shí)是將一個方法分成了這樣幾段來執(zhí)行
// 下面 五行一起的豎線(|) 用一個大括號表示出來會更直觀一點(diǎn) function *f3() { // 調(diào)用 next("N") 時運(yùn)行的代碼 console.log("0"); let y1 = yield 1; return 1; // | 封裝成 {value: 1, done: false} 返回 // | // | 這兩行等同于 let y1 = yield 1; // 調(diào)用 next("I") 時運(yùn)行的代碼 // | let y1 = "I"; // | console.log("1: " + y1); return y1 + 2; // | 封裝成 {value: "I2", done: false} 返回 // | // | 這兩行等同于 let y2 = yield y1 + 2; // 調(diào)用 next("L") 時運(yùn)行的代碼 // | let y2 = "L"; // | console.log("2: " + y2); return (y2 + 3); // | 封裝成 {value: "L3", done: false} 返回 // | // | 這兩行等同于 let y3 = yield (y2 + 3); // 調(diào)用 next("S") 時運(yùn)行的代碼 // | let y3 = "S"; // | console.log("3: " + y3); return (y3); // | 封裝成 {value: "S", done: false} 返回 // | // | 這兩行等同于 let y4 = (yield y3) + 4; // 調(diào)用 next("H") 時運(yùn)行的代碼 // | let y4 = ("H") + 4; // | console.log("4: " + y4); return "??"; // 封裝成 {value: "??", done: true} 返回 // done 為 true 之后, 再 next() 就都返回那一個了 }
再回頭想一想就知道了, 第一次運(yùn)行 next("N") 的時候, 傳進(jìn)去的 N 是會被忽略的, 因?yàn)榈谝淮?next() 傳的值沒有 yield 前面來接收. 再去看書也好, 看查到的文章也好, 第一次 next() 都是沒有傳過參數(shù)
感覺 yield 就是為了迭代而生的, 迭代完全可以就用 for 啊, 但是卻繞成這樣, 也不知道這是為哪般! 就這還能新弄一個 for of 玩出花來, 因?yàn)槊繄?zhí)行 next() 才會執(zhí)行那一段段, 還美其名曰 "咱們終于可以異步了"
async/await再是 es7 開始有的這倆關(guān)鍵字, 看了一個大廠的面試題, 自己為了加深對這兩個關(guān)鍵字的理解改了一下成下面這樣
async function async1() { console.log("A"); console.log(await async2()); return "B"; } async function async2() { console.log("C"); return "D"; } console.log("E"); setTimeout(function() { console.log("F"); }, 0); async1().then(function(r) { console.log(r); }); new Promise(function(resolve, reject) { console.log("G"); resolve(); }).then(function() { console.log("H"); }); console.log("I");
在 chrome 73.0.3683.75 底下的輸出是:
// 這個 undefined 的意思應(yīng)該主要是用來分隔宏任務(wù)的, 也就是前面的主線和任務(wù)隊(duì)列是在一起的 E A C G I D H B undefined F
在 firefox 60.5.1 底下的輸出
// 這個 undefined 的意思應(yīng)該只是用來分隔主線的, 任務(wù)隊(duì)列和宏任務(wù)在一起了 E A C G I undefined H D B F
在 opera 58.0.3135.107 底下的輸出是:
// 這個 undefined 應(yīng)該跟 chrome 里面是一樣的 E A C G I H D B undefined F
明顯 D H B 是比較合理的. 在 firefox 和 opera 的實(shí)現(xiàn)中明顯是有問題的, 想像得到, 低版本一點(diǎn)的 chrome 也可能是后面的結(jié)果
終還有像 var let const 這種一個簡單的賦值都能玩出這么多花樣(當(dāng)然, 這可以說是歷史遺留問題導(dǎo)致的)
老實(shí)說, 我覺得這更多是為了: "別的語言有, 咱們這么前衛(wèi)的語言當(dāng)然應(yīng)該要有!"
...
就這么樣一門語言, 居然可以流行成現(xiàn)在這樣, 只能說這個世界是真奇妙
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/102704.html
摘要:迭代器是一種特殊對象,每一個迭代器對象都有一個,該方法返回一個對象,包括和屬性。默認(rèn)情況下定義的對象是不可迭代的,但是可以通過創(chuàng)建迭代器。在迭代器中拋出錯誤不再執(zhí)行生成器返回語句生成器中添加表示退出操作。迭代器是一個對象。 迭代器(Iterator) ES5實(shí)現(xiàn)迭代器 迭代器是什么?遇到這種新的概念,莫慌張。 迭代器是一種特殊對象,每一個迭代器對象都有一個next(),該方法返回一個對...
摘要:在年正式發(fā)布了,簡稱,又稱為。再次簡寫循環(huán)迭代數(shù)組每個元素都執(zhí)行一次回調(diào)函數(shù)。方法用于調(diào)用數(shù)組的每個元素,并將元素傳遞給回調(diào)函數(shù)。注意對于空數(shù)組是不會執(zhí)行回調(diào)函數(shù)的。 轉(zhuǎn)載請注明出處 原文連接 http://blog.huanghanlian.com/article/5c7aa6c7bf3acc0864870f9d es6 是什么 首先弄明白ECMA和js的關(guān)系。ECMA是標(biāo)準(zhǔn),Jav...
摘要:在年正式發(fā)布了,簡稱,又稱為。再次簡寫循環(huán)迭代數(shù)組每個元素都執(zhí)行一次回調(diào)函數(shù)。方法用于調(diào)用數(shù)組的每個元素,并將元素傳遞給回調(diào)函數(shù)。注意對于空數(shù)組是不會執(zhí)行回調(diào)函數(shù)的。 轉(zhuǎn)載請注明出處 原文連接 http://blog.huanghanlian.com/article/5c7aa6c7bf3acc0864870f9d es6 是什么 首先弄明白ECMA和js的關(guān)系。ECMA是標(biāo)準(zhǔn),Jav...
摘要:常用知識總結(jié)之前總結(jié)了中的一些知識點(diǎn)。在年正式發(fā)布了,簡稱,又稱為。作為構(gòu)造函數(shù)的語法糖,同時有屬性和屬性,因此同時存在兩條繼承鏈。子類的屬性,表示構(gòu)造函數(shù)的繼承,總是指向父類。 ES6常用知識總結(jié) 之前總結(jié)了es5中js的一些知識點(diǎn)。這段時間看了石川blue老師講解的es6課程,結(jié)合阮一峰老師的es6教程,隨手做了一些筆記和總結(jié)分享給大家。內(nèi)容還是es6主要的知識點(diǎn),基本沒有什么創(chuàng)新...
閱讀 4953·2023-04-25 18:47
閱讀 2685·2021-11-19 11:33
閱讀 3456·2021-11-11 16:54
閱讀 3110·2021-10-26 09:50
閱讀 2555·2021-10-14 09:43
閱讀 679·2021-09-03 10:47
閱讀 684·2019-08-30 15:54
閱讀 1509·2019-08-30 15:44