Topic Introduction
The following is the original text of the interview questions I copied from the Internet:
Achieve one LazyMan,You can call it as follows:
LazyMan("Hank")output:
Hi! This is Hank!
LazyMan("Hank").sleep(10).eat("dinner")output
Hi! This is Hank!
//Wait 10 seconds.
Wake up after 10
Eat dinner~
LazyMan("Hank").eat("dinner").eat("supper")output
Hi This is Hank!
Eat dinner~
Eat supper~
LazyMan("Hank").sleepFirst(5).eat("supper")output
//Wait for 5 seconds.
Wake up after 5
Hi This is Hank!
Eat supper
//And so on.
II. Points of Topic Investigation
First, I declare: I am not a Wechat employee, the inspection point is my speculation, maybe not, haha!
_1. Method Chain Call
_2. The Use of Classes and the Thought of Object-Oriented Programming
_3. Application of Design Patterns
_4. Code decoupling
5. The principle of minimum knowledge, i.e. Law of Demeter
_6. Writing structure and naming of code
3. Analysis of Topic Thought
Look at the output example of the title, we can confirm that this is personified output, that is to say, we should write a class to define a class of people, called LazyMan. Can output name, eat, sleep and other behavior.
_2. As can be seen from the output sentence, sleepFrist has the highest priority, while other behaviors have the same priority.
From three examples, we have to call LazyMan to initialize a person in order to continue the follow-up behavior, so LazyMan is an interface.
_4. Sentences are executed in the order in which methods are called, and they are a queue.
4. Implementing code in observer mode
_4.1 Coding in modular mode
(function(window, undefined){ )(window);
_4.2 Declares a variable taskList for storing queue information required
(function(window, undefined){ var taskList = []; )(window);
_In a queue, the storage of a single item is designed as a json to store messages that need to be triggered and a list of parameters needed for method execution. For example, LazyMan('Hank') needs the following storage information.
{ 'msg':'LazyMan', 'args':'Hank' }
When the LazyMan method is executed, the subscription method is invoked, and the information needed to execute is stored in the taskList and cached.
_Stored information will be retained, and other publishing methods will be extracted, executed and output.
_4.3 Subscription Method
_Call method design of subscribe method: subscribe("lazyMan", "Hank")
(function(window, undefined){ var taskList = []; // Subscribe function subscribe(){ var param = {}, args = Array.prototype.slice.call(arguments); if(args.length < 1){ throw new Error("subscribe Parameters cannot be null!"); } param.msg = args[0]; // Message name param.args = args.slice(1); // parameter list if(param.msg == "sleepFirst"){ taskList.unshift(param); }else{ taskList.push(param); } } )(window);
_Use a param variable to organize the information that needs to be stored, then push into taskList and cache it.
In particular, if sleepFirst, it is placed at the head of the queue.
_4.4 Publishing Method
(function(window, undefined){ var taskList = []; // Release function publish(){ if(taskList.length > 0){ run(taskList.shift()); } } )(window);
_Read out the stored information in the queue and give it to the run method (tentative, follow-up implementation) to execute. This restricts the execution of only one publication at a time to maintain that the methods in the queue can be executed one by one.
In addition, the reason for using shift() here is to remove one from the queue and avoid repeated execution.
_4.5 Implementing LazyMan Class
// class function LazyMan(){}; LazyMan.prototype.eat = function(str){ subscribe("eat", str); return this; }; LazyMan.prototype.sleep = function(num){ subscribe("sleep", num); return this; }; LazyMan.prototype.sleepFirst = function(num){ subscribe("sleepFirst", num); return this; };
_LazyMan class will be implemented, with eat, sleep, sleep Frist and other behavior.
Trigger an action, record it once in taskList, and return the current object to support chain invocation.
_4.6 Packaging Method for Output console.log
// Output text function lazyManLog(str){ console.log(str); }
_Why do we have to wrap a layer for console.log? Because in actual combat projects, labor and economics often modify the UI of output prompts. If you call console.log directly everywhere, it's a lot of trouble to change.
In addition, if you want to be compatible with IE and other low-level version browsers, you can also easily modify.
That's the Don't Repeat Youself principle.
_.4.7 The Method of Implementing Specific Implementation
// Specific methods function lazyMan(str){ lazyManLog("Hi!This is "+ str +"!"); publish(); } function eat(str){ lazyManLog("Eat "+ str +"~"); publish(); } function sleep(num){ setTimeout(function(){ lazyManLog("Wake up after "+ num); publish(); }, num); } function sleepFirst(num){ setTimeout(function(){ lazyManLog("Wake up after "+ num); publish(); }, num); }
The focus here is to solve the problem of delayed invocation when setTimeout executes, that is, thread asynchronous execution. Only after this method is successfully executed, a message publish() is issued again, prompting the next queue information to be executed. Otherwise, it will wait all the time.
_4.8 Implementing the run method to identify which specific method to call is a general console
// Quack function run(option){ var msg = option.msg, args = option.args; switch(msg){ case "lazyMan": lazyMan.apply(null, args);break; case "eat": eat.apply(null, args);break; case "sleep": sleep.apply(null,args);break; case "sleepFirst": sleepFirst.apply(null,args);break; default:; } }
This method is somewhat like a duck-type interface, so the comment is called a duck-call.
The run method receives a single message in the queue, reads it out, sees what type of message it is, and then executes the corresponding method.
_4.9 Expose the interface LazyMan so that external calls can be made
(function(window, undefined){ // Exposed interface window.LazyMan = function(str){ subscribe("lazyMan", str); setTimeout(function(){ publish(); }, 0); return new LazyMan(); }; )(window);
_The publish method in interface LazyMan must be invoked using setTimeout. This allows the threads executed by publish() to be delayed and suspended. After the equal-chain method has been executed, the thread is idle, and then the publish() is executed.
In addition, this is an external interface, so when invoked, a new LazyMan will be returned for invocation.
Five, summary
1. benefits
_Using the observer mode, the code can be decoupled to a reasonable degree, so that later maintenance is more convenient.
For example, if I want to modify the eat method, I just need to focus on the implementation of eat() and LazyMan.prototype.eat. Elsewhere, I can ignore it. This conforms to the principle of minimum knowledge.
2. deficiency
LazyMan.prototype.eat method parameters, in fact, can be replaced by arguments, I did not write out, for fear of making it too complex, let's leave an optimization point.
_The unshift and shift methods are used without considering the compatibility of low-version IE browsers.
6. Complete source code and online demo
_The full source code is already on my gitHub
Mask entry: https://github.com/wall-wxk/blogDemo/blob/master/2017/01/22/lazyMan.html
demo access address: https://wall-wxk.github.io/blogDemo/2017/01/22/lazyMan.html
demo needs to open the console and debug the code in the console.
Seven.
_Some people on the Internet have also implemented lazyMan, but I do not like and agree with the way it is implemented, but it is also a way of thinking, here by the way to post for everyone to see.
How to Implement a LazyMan: http://web.jobbole.com/89626/
Read the original text: www.jianshu.com/p/f1b7cb456d37