微信LazyMan筆試題的深入解析和實現

2021-07-26 11:18:48 字數 4304 閱讀 4785

以下是我copy自網上的面試題原文:

實現乙個lazyman,可以按照以下方式呼叫:

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

以此類推。

1.方法鏈式呼叫

2.類的使用和物件導向程式設計的思路

3.設計模式的應用

4.**的解耦

5.最少知識原則,也即 迪公尺特法則(law of demeter)

6.**的書寫結構和命名

1.看題目輸出示例,可以確定這是擬人化的輸出,也就是說:應該編寫乙個類來定義一類人,叫做lazyman。可以輸出名字、吃飯、睡覺等行為。

2.從輸出的句子可以看出,sleepfrist的優先順序是最高的,其他行為的優先順序一致。

3.從三個例子來看,都得先呼叫lazyman來初始化乙個人,才能繼續後續行為,所以lazyman是乙個介面。

4.句子是按呼叫方法的次序進行順序執行的,是乙個佇列。

4.1 採用模組模式來編寫**

(function(window,

undefined))(window);

4.2 宣告乙個變數tasklist,用來儲存需要佇列資訊

(function(window,

undefined))(window);

佇列中,單個項的儲存設計為乙個json,儲存需要觸發的訊息,以及方法執行時需要的引數列表。比如lazyman('hank'),需要的儲存資訊如下。

當執行lazyman方法的時候,呼叫訂閱方法,將需要執行的資訊存入tasklist中,快取起來。

儲存的資訊,會先保留著,等發布方法進行提取,執行和輸出。

4.3 訂閱方法

訂閱方法的呼叫方式設計:subscribe("lazyman", "hank")

(function(window,

undefined),

args =

array.prototype.slice.call(arguments);

if(args.length

<

1)param.msg

= args[0];

// 訊息名

param.args

=args.slice(1);

// 引數列表

if(param.msg

=="sleepfirst")

else

}})(window);

用乙個param變數來組織好需要儲存的資訊,然後push進tasklist中,快取起來。

特別的,如果是sleepfirst,則放置在佇列頭部。

4.4 發布方法

(function(window,

undefined)

}})(window);

將佇列中的儲存資訊讀取出來,交給run方法(暫定,後續實現)去執行。這裡限定每次發布只執行乙個,以維持佇列裡面的方法可以挨個執行。

另外,這裡使用shift()方法的原因是,取出乙個,就在佇列中刪除這乙個,避免重複執行。

4.5 實現lazyman類

// 類

function

lazyman(){};

lazyman.prototype.eat

=function(str);

lazyman.prototype.sleep

=function(num);

lazyman.prototype.sleepfirst

=function(num);

將lazyman類實現,具有eat、sleep、sleepfrist等行為。

觸發一次行為,就在tasklist中記錄一次,並返回當前物件,以支援鏈式呼叫。

4.6 實現輸出console.log的包裝方法

// 輸出文字

function

lazymanlog(str)

為什麼還要為console.log包裝一層,是因為在實戰專案中,產經經常會修改輸出提示的ui。如果每一處都用console.log直接呼叫,那改起來就麻煩很多。

另外,如果要相容ie等低階版本瀏覽器,也可以很方便的修改。

也就是dry原則(don't repeat youself)。

4.7 實現具體執行的方法

// 具體方法

function

lazyman(str)

function

eat(str)

function

sleep(num), num*

1000);

}function

sleepfirst(num), num*

1000);

}

這裡的重點是解決settimeout執行時會延遲呼叫,也即執行緒非同步執行的問題。只有該方法執行成功後,再發布一次訊息publish(),提示可以執行下乙個佇列資訊。否則,就會一直等待。

4.8 實現run方法,用於識別要呼叫哪個具體方法,是乙個總的控制台

// 鴨子叫

function

run(option)

}

這個方法有點像鴨式辨型介面,所以注釋叫鴨子叫

run方法接收佇列中的單個訊息,然後讀取出來,看訊息是什麼型別的,然後執行對應的方法。

4.9 暴露介面lazyman,讓外部可以呼叫

(function(window,

undefined),

0);return

newlazyman();

};})(window);

介面lazyman裡面的publish方法必須使用settimeout進行呼叫。這樣能讓publish()執行的執行緒延後,掛起。等鏈式方法都執行完畢後,執行緒空閒下來,再執行該publish()

另外,這是乙個對外介面,所以呼叫的時候,同時也會new 乙個新的lazyman,並返回,以供呼叫。

1. 好處

使用觀察者模式,讓**可以解耦到合理的程度,使後期維護更加方便。

比如我想修改eat方法,我只需要關注eat()lazyman.prototype.eat的實現。其他地方,我都可以不用關注。這就符合了最少知識原則

2. 不足

lazyman.prototype.eat這種方法的引數,其實可以用arguments代替,我沒寫出來,怕弄得太複雜,就留個優化點吧。

使用了unshift和shift方法,沒有考慮到低版本ie瀏覽器的相容。

完整原始碼已經放在我的github上

原始碼入口:

demo需要開啟控制台,在控制台中除錯**。

網上有人也實現了lazyman,但是實現的方式我不是很喜歡和認同,但是也是一種思路,這裡順便貼出來給大夥看看。

如何實現乙個lazyman:

微信前端面試題 js實現LazyMan

實現乙個lazyman,可以按照以下方式呼叫 lazyman hank 輸出 hi this is hank lazyman hank sleep 10 eat dinner 輸出 hi this is hank 等待10秒.wake up after 10 eat dinner lazyman h...

微策略筆試題

題目 序列123.n,n介於3和9之間,在其中加入 或者空格,使其和為0,如123456 1 2 3 4 5 6 7 等價於1 23 45 67 0。請問,如何獲得所有組合?使用遞迴和非遞迴。下面的 是別人寫的,個人認為很好就收藏了。c 序列123.n,n介於3和9之間,在其中加入 或者空格,使其和...

求解微信紅包(2016騰訊校招筆試題)

題目描述 請幫小明找到該紅包金額。寫出具體演算法思路和 實現,要求演算法盡可能高效。解題思路 這道題看上去感覺挺簡單,最簡單的方法就是分別算出每個紅包金額出現次數,再找出出現次數過半的金額。但是這麼常規做法肯定 超出了題目所給的限制條件 時間複雜度和空間複雜度 儘管題目沒有明確表明。首先仔細看題目給...