摘要:首先我們來(lái)講這個(gè)棧在中,每當(dāng)有函數(shù)被執(zhí)行的時(shí)候都會(huì)在當(dāng)前的執(zhí)行堆棧中創(chuàng)建一個(gè)新的堆棧幀,并放到棧頂。因?yàn)槭擎準(zhǔn)秸{(diào)用,所以代碼一直在同一個(gè)作用于中執(zhí)行,也就是說(shuō)當(dāng)前的堆棧幀一直沒(méi)有被移出棧。
前言
前幾天在稀土上看到一篇面試的帖子,里面微信有一道題是lazyman的實(shí)現(xiàn),具體要做的事情就是
LazyMan(“Hank”) //Hi! This is Hank! LazyMan(“Hank”).sleep(10).eat(“dinner”) // Hi! This is Hank! // 等待10秒.. // Wake up after 10 // Eat dinner~ LazyMan(“Hank”).eat(“dinner”).eat(“supper”) // Hi This is Hank! // Eat dinner~ // Eat supper~ LazyMan(“Hank”).sleepFirst(5).eat(“supper”) // 等待5秒 // Wake up after 5 // Hi This is Hank! // Eat supper
這道題考察的肯定不是實(shí)現(xiàn)這個(gè)函數(shù)的能力問(wèn)題,應(yīng)該是流程控制的問(wèn)題。解決思路應(yīng)該是將所有的人如都存放到一個(gè)數(shù)組中,并在所有的方法執(zhí)行完之后一次性的輸出,實(shí)現(xiàn)的代碼如下:
function _LazyMan(name) { this.tasks = []; var self = this; var fn =(function(n){ var name = n; return function(){ console.log("Hi! This is " + name + "!"); self.next(); } })(name); this.tasks.push(fn); setTimeout(function(){ self.next(); }, 0); // 在下一個(gè)事件循環(huán)啟動(dòng)任務(wù) } /* 事件調(diào)度函數(shù) */ _LazyMan.prototype.next = function() { var fn = this.tasks.shift(); fn && fn(); } _LazyMan.prototype.eat = function(name) { var self = this; var fn =(function(name){ return function(){ console.log("Eat " + name + "~"); self.next() } })(name); this.tasks.push(fn); return this; // 實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用 } _LazyMan.prototype.sleep = function(time) { var self = this; var fn = (function(time){ return function() { setTimeout(function(){ console.log("Wake up after " + time + "s!"); self.next(); }, time * 1000); } })(time); this.tasks.push(fn); return this; } _LazyMan.prototype.sleepFirst = function(time) { var self = this; var fn = (function(time) { return function() { setTimeout(function() { console.log("Wake up after " + time + "s!"); self.next(); }, time * 1000); } })(time); this.tasks.unshift(fn); return this; } /* 封裝 */ function LazyMan(name){ return new _LazyMan(name); }
我自己在思考解決方法的時(shí)候最讓我困惑的就是如果判斷Lazyman對(duì)象的方法被調(diào)用結(jié)束了?我甚至為了這個(gè)問(wèn)題坐過(guò)了站。。。后來(lái)當(dāng)我看到這段代碼的時(shí)候,發(fā)現(xiàn)一個(gè)簡(jiǎn)單的setTimeout就解決了這個(gè)問(wèn)題,為什么呢???
并發(fā)模型與Event?Loop這張圖是MDN對(duì)Event Loop的解釋,這張圖上分為三個(gè)部分,分別是隊(duì)列、棧、和堆。我們?cè)诶斫鈒azyman的過(guò)程中需要知道的就是隊(duì)列和棧。首先我們來(lái)講這個(gè)棧:
在js中,每當(dāng)有函數(shù)被執(zhí)行的時(shí)候都會(huì)在當(dāng)前的執(zhí)行堆棧中創(chuàng)建一個(gè)新的堆棧幀,并放到棧頂。這個(gè)堆棧幀中包含當(dāng)前執(zhí)行的函數(shù)的參數(shù)和局部變量。(有沒(méi)有感覺(jué)很熟悉,沒(méi)錯(cuò),這就是我們理解作用域鏈的時(shí)候的那個(gè)棧)而當(dāng)我們的函數(shù)執(zhí)行完之后,這個(gè)堆棧幀就會(huì)從當(dāng)前棧中移除。
隊(duì)列就是JS中用來(lái)處理異步事件的隊(duì)列,每當(dāng)有新的異步事件發(fā)生,就會(huì)添加一個(gè)新的消息到隊(duì)列的尾部。當(dāng)之前提到的棧為空時(shí),JS就會(huì)來(lái)處理隊(duì)列中的消息。
舉個(gè)例子來(lái)說(shuō)就是:
var a = function() { setTimeout(function(){console.log(1)},0) } var b = function(){ a() console.log(2) } // 2 // 1
這里需要注意的有
就算你不在函數(shù)中使用setTimeout,而是在全局環(huán)境中使用,setTimeout也是在正常的同步代碼執(zhí)行完之后執(zhí)行,這是因?yàn)檫€有宿主環(huán)境在。
setTimeOut是經(jīng)過(guò)一段時(shí)間之后直接向隊(duì)列中加入一個(gè)消息,而普通的http請(qǐng)求是等到有返回結(jié)果了才會(huì)將消息加入到隊(duì)列中。
普通的異步事件如果沒(méi)有事件監(jiān)聽(tīng)器的話是不會(huì)操作隊(duì)列的,消息是直接被忽視掉。
Lazyman中的setTimeoutLazyman中的`setTimeout不是單單的在函數(shù)中執(zhí)行,而是在對(duì)象鏈?zhǔn)秸{(diào)用中執(zhí)行。因?yàn)槭擎準(zhǔn)秸{(diào)用,所以代碼一直在同一個(gè)作用于中執(zhí)行,也就是說(shuō)當(dāng)前的堆棧幀一直沒(méi)有被移出棧。上面的代碼中就是利用了這個(gè)特點(diǎn)解決了如何判斷對(duì)象調(diào)用結(jié)束的問(wèn)題。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/81319.html
摘要:計(jì)算數(shù)組的極值微信面試題獲取元素的最終前端掘金一題目用代碼求出頁(yè)面上一個(gè)元素的最終的,不考慮瀏覽器,不考慮元素情況。 Excuse me?這個(gè)前端面試在搞事! - 前端 - 掘金金三銀四搞事季,前端這個(gè)近年的熱門(mén)領(lǐng)域,搞事氣氛特別強(qiáng)烈,我朋友小偉最近就在瘋狂面試,遇到了許多有趣的面試官,有趣的面試題,我來(lái)幫這個(gè)搞事 boy 轉(zhuǎn)述一下。 以下是我一個(gè)朋友的故事,真的不是我。 ... ja...
摘要:最后畫(huà)幾張粗糙的圖,簡(jiǎn)單描述一下這個(gè)執(zhí)行的過(guò)程因?yàn)槭擎準(zhǔn)秸{(diào)用,所以在鏈上的都會(huì)入棧然后執(zhí)行,額,執(zhí)行棧少畫(huà)了和。。。 前言:昨天在群里討(jin)論(chui)技(niu)術(shù)(pi),有位老鐵發(fā)了一道他面的某公司面試題,順手保存了。今早花了一點(diǎn)時(shí)間把這題做了出來(lái),發(fā)現(xiàn)挺有意思的,決定在今天認(rèn)真工(hua)作(shui)前,與大家分享我的解題方案和思考過(guò)程。 題目如下(可以自己先思考一會(huì)...
摘要:關(guān)于的和以上是關(guān)于與的所有文件指令分析里面意思運(yùn)行的時(shí)候執(zhí)行的是文件,運(yùn)行的時(shí)候執(zhí)行的是文件。前端開(kāi)發(fā)過(guò)程中需要使用到后臺(tái)的的話,可以通過(guò)配置來(lái)將相應(yīng)的后臺(tái)請(qǐng)求代理到專用的服務(wù)器。和這三個(gè)文件就簡(jiǎn)單設(shè)置了環(huán)境變量而已,沒(méi)什么特別的。 關(guān)于vue的npm run dev和npm run build├─build│ ├─build.js│ ├─check-versions.js│ ...
摘要:前言筆者昨天在做某公司的線上筆試題的時(shí)候遇到了最后一道關(guān)于如何實(shí)現(xiàn)的試題,題目如下實(shí)現(xiàn)一個(gè),可以按照以下方式調(diào)用輸出輸出等待秒輸出輸出等待秒以此類推。 前言 筆者昨天在做某公司的線上筆試題的時(shí)候遇到了最后一道關(guān)于如何實(shí)現(xiàn)LazyMan的試題,題目如下 實(shí)現(xiàn)一個(gè)LazyMan,可以按照以下方式調(diào)用:LazyMan(Hank)輸出:Hi! This is Hank!LazyMan(Hank...
摘要:能不能支持?jǐn)?shù)據(jù)丟失啊可以的,參考我們之前說(shuō)的那個(gè)數(shù)據(jù)零丟失方案其實(shí)一個(gè)肯定是很復(fù)雜的,其實(shí)這是個(gè)開(kāi)放題,就是看看你有沒(méi)有從架構(gòu)角度整體構(gòu)思和設(shè)計(jì)的思維以及能力。其實(shí)回答這類問(wèn)題,說(shuō)白了,起碼不求你看過(guò)那技術(shù)的源碼,起碼你大概知道那個(gè)技術(shù)的基本原理,核心組成部分,基本架構(gòu)構(gòu)成,然后參照一些開(kāi)源的技術(shù)把一個(gè)系統(tǒng)設(shè)計(jì)出來(lái)的思路說(shuō)一下就好 比如說(shuō)這個(gè)消息隊(duì)列系統(tǒng),我們來(lái)從以下幾個(gè)角度來(lái)考慮一下 (1...
閱讀 610·2021-10-19 11:45
閱讀 1531·2021-09-30 09:48
閱讀 1534·2021-08-16 10:56
閱讀 805·2021-07-26 23:38
閱讀 3259·2019-08-30 13:15
閱讀 2646·2019-08-30 12:45
閱讀 1902·2019-08-29 12:14
閱讀 2217·2019-08-26 18:42