“This article has participated in the good article summoning order activity, click to view: back end, big front double track submission, 20,000 yuan prize pool for you to challenge”

background

In January this year, I was very lucky to participate in the first interview of Alibaba in my life

In one side, the interviewer did not ask too many questions, the first is three pen questions, an hour to complete

The first two questions are array of questions, with half an hour, A out, at that time write very cool, so did not record the question

In the third question, the building Lord failed, wrote half, card train of thought, finally still did not write complete 🙃. Finally, I took note of the question when the interviewer wasn’t looking

This topic in the backlog inside hang for half a year, these few smallpox a lot of time to study this problem, finally solved, the next is the original problem and my problem solving process (in the face of the wind! ✨)

Topic describes

To implement an EatMan, EatMan can have some examples of the following behaviors:1. EatMan('Hank') Output: Hi! This is Hank!2. EatMan('Hank').eat('dinner').eat('supper'Output) Hi! This is Hank! Eat dinner~ Eat supper~3. EatMan('Hank').eat('dinner').eatFirst('lunch'Output Eat lunch~ Hi! This is Hank! Eat dinner~4. EatMan('Hank').eat('dinner').eatFirst('lunch').eatFirst('breakfast'Output Eat breakfast~ Eat lunch~ Hi! This is Hank! Eat dinner~Copy the code

Train of thought analysis and hand tear code

(PS: The answer is long, I hope you can read it patiently.)

Step 1: Give it a try 🐱🏍

We examine the first and second test cases of the problem

 1. EatMan('Hank'Output) Hi! This is Hank!2. EatMan('Hank').eat('dinner').eat('supper'Output) Hi! This is Hank! Eat dinner~ Eat supper~Copy the code

Thought analysis

It’s not hard to see what they want to examine

  1. The use of JavaScript classes (why classes? Because we can takeeatThis method is considered a property of the EatMan instance.
  2. Implementation of chained calls

Let’s try to write some code

Code implementation

/* * @Date: 2021-07-15 13:49:04 * @LastEditors: cunhang_wwei * @LastEditTime: 2021-07-15 14:08:34 * @Description: EatMan's initial attempt */

class MyEatMan {
    constructor(name) {
        this.name = name

        this.printName(this.name)
    }

    // Print the name
    printName(name) {
        console.log(`Hi! This is ${name}! `)}eat(thing) {
        console.log(`Eat ${thing}~ `)
        // Return this. Pass the pointer to implement the chained call
        return this}}/ / instantiate
function EatMan(name) {
    return new MyEatMan(name)
}
Copy the code
// Test case 1
EatMan('Hank')
/** * output * Hi! This is Hank! * /

// Test case 2
EatMan('Hank').eat('dinner').eat('supper')
/** * output * Hi! This is Hank! * Eat dinner~ * Eat supper~ */
Copy the code

Let’s test it out

Discovery returns the answer we’re looking for

Is a little small sense of achievement 😀, that we continue!

Step 2: Advanced 🐱👓

Analyze the third and fourth test cases

  3. EatMan('Hank').eat('dinner').eatFirst('lunch'Output Eat lunch~ Hi! This is Hank! Eat dinner~4. EatMan('Hank').eat('dinner').eatFirst('lunch').eatFirst('breakfast'Output Eat breakfast~ Eat lunch~ Hi! This is Hank! Eat dinner~Copy the code

Thought analysis

We see a big change, eatFirst changes the order in which the functions are executed

Experienced bosses see the order and get it right away

The knowledge of task queues is examined

Building Lord before was in this place card train of thought, did not make finally 😅

We had to make a big change to the code we wrote in the first step, and that was to add the task queue

Code implementation

class MyEatMan {
    constructor(name) {
        this.name = name
        // Queue the functions that need to be executed
        this.tasks = []
        // The first task
        const task = this.printName(this.name)
        // Put it in the task queue
        this.tasks.push(task)
        / / execution
        this.run()
    }

    // Print the name
    printName(name) {
        return function() {
            console.log(`Hi! This is ${name}! `)}}// the eat function queues one task each time it is called
    eat(thing) {
        const task = function() {
            console.log(`Eat ${thing}~ `)}this.tasks.push(task)
        this.run()
        return this
    }

    // run Executes the task
    run() {
        / / out of the team
        const currTask = this.tasks.shift()
        / / execution
        currTask && currTask()
    }
}
Copy the code

Let’s test it out

// Test case 1
EatMan('Hank')
/** * output * Hi! This is Hank! * /
Copy the code
// Test case 2
EatMan('Hank').eat('dinner').eat('supper')
/** * output * Hi! This is Hank! * Eat dinner~ * Eat supper~ */
Copy the code

If the output is consistent with the answer, then our transformation is OK

Step 3: Perfect 👏

Finally, we implement the eatFirst function

Thought analysis

  1. eatFirstFunction has a queue-jumping functioneatFirstThen the task can be inserted into the queue head of the task queue
  2. new MyEatMan()The task queue cannot be executed immediately, but is executed after the task has been queued
  3. When each task is completed, the next task is triggered to ensure the continuity of tasks

Code implementation

class MyEatMan {
    constructor(name) {
        this.name = name
        // Queue the functions that need to be executed
        this.tasks = []
        // The first task
        const task = this.printName(this.name)
        // Put it in the task queue
        this.tasks.push(task)
        // To ensure that all tasks are executed after they have been queued, create a macro task and place the time to execute the task in the next event loop
        let self = this
        setTimeout(function () {
            // console.log('tasks', self.tasks)
            self.run()
        }, 0)}// Print the name
    printName(name) {
        let self = this
        return function () {
            console.log(`Hi! This is ${name}! `)
            self.run()
        }
    }

    // the eat function queues one task at a time and implements chained calls
    eat(thing) {
        let self = this
        const task = function () {
            console.log(`Eat ${thing}~ `)
            self.run()
        }

        this.tasks.push(task)
        return this
    }

    // eatFirst function, who initializes last, who executes first, and can implement chain calls
    eatFirst(thing) {
        let self = this
        const task = function () {
            console.log(`Eat ${thing}~ `)
            self.run()
        }

        // Insert into the head of the queue
        this.tasks.unshift(task)
        return this
    }

    // run Executes the task
    run() {
        / / out of the team
        const currTask = this.tasks.shift()
        / / execution
        currTask && currTask()
    }
}


function EatMan(name) {
    return new MyEatMan(name)
}
Copy the code

We use test cases to test

// Test case 3

EatMan('Hank').eat('dinner').eatFirst('lunch')
/** * output * Eat lunch~ * Hi! This is Hank! * Eat dinner~ */
Copy the code

// Test case 4
EatMan('Hank').eat('dinner').eatFirst('lunch').eatFirst('breakfast')
/** * output * Eat breakfast~ * Eat lunch~ * Hi! This is Hank! * Eat dinner~ */
Copy the code

The output is exactly the same as the answer!

The job is done!

The last

About the interview, the interviewer is very merciful, let me into the second interview, but I was not fully prepared at that time, the answer is not very good, the second interview on the hang 🤦♂️

I hope you have learned something after reading this article, if it can help you in front of the screen, to solve this problem, that would be the best

I am 970, good good study will not be bad, we make progress together!

And finally, finally, push in! Place shenzhen, I hope the big guys positive message ah!