I recently participated in the front-end internship in my junior year. The interview was three rounds of technical interview and one round of HR interview. I have got the offer successfully.

One side (50 min)

I was interviewed by a young brother in his early 20s, the first interview I was still quite nervous, fortunately the little brother is kind and amiable, for the problem will not be difficult for me, but give me a lot of tips (to praise)

The first is self-introduction, asked me to learn the way and method of the front end of what, is a warm opening bar, and then specific questions.

1. New features of ES6

I first said const and let, the upperclassman directly asked me to elaborate on let and const

  1. Variables declared by lets, const, are only valid within the block of code they are in, implicitly intercepting scope.
  2. A temporary dead zone in which variable declarations are promoted but will not be assigned toundefinedCannot be used before declaration.
  3. Duplicate declarations are not allowed.

Then I gave two examples to illustrate:

const a = 1
const a = 2
console.log(a)
Copy the code

SyntaxError: Identifier ‘a’ has already been declared, let and const in ES6 are not allowed to declare variables repeatedly.

const b = []
b.push(1)
console.log(b)
Copy the code

The output is [1], which is the difference between a primitive type and a reference type, and b refers only to the memory address of the array.

2. Introduction methods and differences of modules before ES6

Before ES6, modules were mainly introduced by CommonJS and AMD.

Then let me explain the differences between CommonJs and ES6 modules:

  1. First, the CommonJS exported value is a shallow copy, and once a value is printed, changes within the module do not affect that value. While ES6 export adopts real-time binding, which is to export its memory address. Import dynamically loads module values, and variables are always bound to the module where they are, and cannot be re-assigned.
  2. ES6 modular imports are asynchronous imports and CommonJS imports are synchronous imports. This is related to the fact that ES6 modules are typically used on the Web side, while CommonJS is used on the server side.
  3. CommonJS imports support dynamic importsrequire(`${path}/xx.js`), ES6 modular import is not supported. A draft is available.
  4. ES6 modularity will compile intorequire/exportsTo execute.

3. Array traversal

Implement [1,2,3] => [2,4,6]

function fn(arr) {
    return arr.map(item => item * 2)
}
Copy the code

4

For the input string, remove the character ‘b’ and successive occurrences of ‘a’ and ‘c’, for example:

  'aacbd' -> 'ad'
  'aabcd' -> 'ad'
  'aaabbccc' -> ' '
Copy the code

This continuous AC needs to pay attention to the following, at first I thought that using the stack can also be troublesome, the senior reminded the re, directly use the re:

function fn(str) {
  let res = str.replace(/b+/g, ' ');
  while(res.match(/(ac)+/)) {
    res = res.replace(/ac/, ' ')}return res;
}
Copy the code

5. CSS9 GongGe

Problem: create CSS9 cells, 3*3 cells, the length and width of each cell is unknown, requiring adaptive and accurate allocation.

For this exact assignment, it is doomed to use width: 1/3 is not enough, so use Flex layout:

<! --HTML--> <div class="container">
  <div class="wrapper">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
  <div class="wrapper">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
  <div class="wrapper">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div> </div> </div> <! --CSS--> .container { display: flex; flex-direction: column; flex-wrap: nowrap; } .wrapper { display: flex; flex: 1; flex-direction: row; flex-wrap: nowrap; } .item { flex: 1; }Copy the code

React Virtual Dom (1) Diff algorithm (2) mapping to real Dom \

React virtual DOM and Diff algorithms

React abstracts the DOM into a virtual DOM (VDOM), and then uses the Diff algorithm to render only the parts that have changed.

VDOM

The structure of DOM tree is simulated with JS, and the changes of DOM tree are compared with JS.

When we need to create or update elements, React first creates and changes the VitrualDom object, and then renders the VitrualDom object into the real DOM.

Advantages of the virtual DOM:

  1. Functional programming. The UI depends on the data.
  2. Opens the door to cross-platform. Provides a unified JS layer object, according to different platforms to develop different rendering methods, bringing the ability of cross-platform rendering.

The Diff algorithm

After creating a React element tree, a new React element tree will be created during update. React uses the Diff algorithm to compare elements in the tree and update only the changed parts to avoid unnecessary performance consumption.

There are two main points:

  1. Two elements of different types produce different trees, direct substitutions.
  2. A set of child nodes at the same level can be distinguished by a unique key.
  3. Level by level recursive comparison.

7. Task queues in NodeJS

Say the output order:

process.nextTick(function() {
  console.log('a')
})

process.nextTick(function() {
  console.log('b')})setImmediate(function() {
  console.log('c')
  process.nextTick(function() {
    console.log('d')})})setImmediate(function() {
  console.log('e')
})

console.log('f')
Copy the code

SetImmediate Does not respond correctly to the question that setImmediate can only be used once.

8. ES6 Character string

The sober of this problem have not met, also won’t, now also forget this problem…

9. Promise implements network timeout judgment

Use Promise to realize network request timeout judgment, more than three seconds as timeout. Using the promise.race method:

const uploadFile = (url, params) => {
  return Promise.race([
    uploadFilePromise(url, params),
    uploadFileTimeout(3000)
  ])
}
function uploadFilePromise(url, params) {
  return new Promise((resolve, reject) => {
    axios.post(url, params, {
      headers: {'Content-Type': 'multipart/form-data'}, // Upload files in formData form withCredentials:true
    }).then(res => {
      if(res.status===200 && res.data.code===0) {
        resolve(res.data.result)
      }else {
        reject(res.data)
      }
    })
  })
}
function uploadFileTimeout(time) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject({timeoutMsg: 'Upload timeout'})
    }, time)
  })
}
Copy the code

Second interview (50 min)

Let me wait ten minutes after one interview. The second interview will begin.

1. Processes and threads

A brief description of operating system processes and threads

  1. Threads are the smallest unit of program execution, while processes are the smallest unit of resources allocated by the operating system.
  2. A process consists of one or more threads, which are different execution paths of code in a process.
  3. Processes are independent of each other, but threads in the same process share the program’s memory space.
  4. Scheduling and switching: Thread context switching is much faster than process context switching.

2. A brief description of locks (deadlocks) in operating systems

Through locking mechanism, it can guarantee that only one process can enter the code of critical area at a certain time point in multi-core and multi-thread environment, so as to ensure the consistency of operation data in critical area.

A deadlock is a phenomenon in which two or more processes are waiting for each other during execution because they are competing for resources and cannot proceed without external forces. In this case, the system is in a deadlock state or a deadlock occurs in the system. These processes that wait for each other forever are called deadlock processes. Two sheep cross a single log bridge.

Deadlock relief and prevention, reasonable allocation of resources…

I didn’t answer that very well.

3. Talk about the types of linked lists

One-way linked lists, two-way linked lists, circular linked lists

4. What is the difference between stack and queue?

A stack is a lifO data structure, often used as a call stack.

Queues are first-in, first-out data structures, commonly used in NodeJS and in browsers.

5. Algorithm

Iterate over all nodes in a binary tree, returning their sum

function numSum(root) {
  if(! root)return 0;
  return root.val + numSum(root.left) + numSum(root.right);
}
Copy the code

6. Algorithm

Given an array, find the maximum number of substring sums of contiguous elements.

Input: [-2,1,-3,4,-1,2,1,-5,4], output: 6Copy the code

The time complexity of the double-layer loop is O(n * n), and the time complexity can be compressed to O(n * logn) using divide and conquer.

function numSum(arr) {
  if(! arr.length)return null;
  if(arr.length < 2) return arr[0];
  let sumMax = arr[0];
  let sumTemp;
  for(let i = 0; i < arr.length; i++) {
    sumTemp = arr[i];
    if(sumTemp > sumMax) sumMax = sumTemp;
    for(let j = i + 1; j < arr.length; j++) {
      sumTemp += arr[j];
      if(sumTemp > sumMax) sumMax = sumTemp; }}return sumMax;
}
Copy the code

7. Introduce your project and the principle of wechat mini program?

A little…

Three sides (1 h)

The difficulty of the three sides is much higher than before

1. What’s new in ES6

Here’s a list of new ES6 features and a brief description of the wave

  • Let, const
  • Deconstruction assignment
  • String, re, numeric, function, array, object extension
  • symbol
  • The Set, the Map
  • Promise
  • Generator
  • async
  • class
  • decorator
  • module

2. The Generator implements a self-execution

Is to implement the following well-known CO module:

function run(gen) {

    return new Promise(function(resolve, reject) {
        if (typeof gen == 'function') gen = gen(); If gen is not an iteratorif(! gen || typeof gen.next ! = ='function') return resolve(gen)

        onFulfilled();

        function onFulfilled(res) {
            var ret;
            try {
                ret = gen.next(res);
            } catch (e) {
                return reject(e);
            }
            next(ret);
        }

        function onRejected(err) {
            var ret;
            try {
                ret = gen.throw(err);
            } catch (e) {
                return reject(e);
            }
            next(ret);
        }

        function next(ret) {
            if (ret.done) return resolve(ret.value);
            var value = toPromise(ret.value);
            if (value && isPromise(value)) return value.then(onFulfilled, onRejected);
            return onRejected(new TypeError('You may only yield a function, promise ' +
                'but the following object was passed: "' + String(ret.value) + '"')); }})}function isPromise(obj) {
    return 'function' == typeof obj.then;
}

function toPromise(obj) {
    if (isPromise(obj)) return obj;
    if ('function' == typeof obj) return thunkToPromise(obj);
    return obj;
}

function thunkToPromise(fn) {
    return new Promise(function(resolve, reject) {
        fn(function(err, res) {
            if (err) return reject(err);
            resolve(res);
        });
    });
}

module.exports = run;
Copy the code

3. Talk about the life cycle of wechat mini program

Page life cycle:

  • OnLoad // executed when the page is created
  • OnShow // page appears in foreground execution
  • OnReady // executes when the page is first rendered
  • OnHide // executed when the page changes from foreground to background
  • OnUnload // Page destruction occurs
  • OnPullDownRefresh // Executed when the drop-down refresh is triggered
  • OnReachBottom // executes when the page hits the bottom
  • OnPageScroll // executed while the page is scrolling
  • OnResize // Executes when the page size changes
  • OnTabItemTap // TAB is executed when clicked

Component declaration cycles (declared in the LifeTimes field) :

  • Created // executes when the component instance is just created
  • Attached // Executes when the component instance enters the page node tree
  • Ready // executed after components are laid out in the view layer
  • Moved // Executed when the component instance is moved to another location in the node tree
  • Detached // Executed when a component instance is removed from a page node
  • Error // Is executed whenever a component method throws an error

4. Say what you know about the React stack

Redux, react-Router, Antd…

5. React-router implements simple grid routes

import { BroserRouter, Route, Switch, Redirect } from 'react-router-dom'

<BroserRouter>
  <Switch>
    <Route path='/login' exact component={Login} />
    <Route path='/' render={() => (
      <Switch>
        <Route paht='/home' component={Home} />
        <Redirect to='/home' />
      </Switch>
    )} />
  </Switch>
</BroserRouter>
Copy the code

Talk about the Redux principle

Redux is a data state management. Briefly introduce the use of Redux data flow, store, Action, reducer, and React.

You can have a look at the source code, the content is not a lot.

7. Tell me about your project

A little…

Tell me about the Koa Onion model

Koa’s onion model: A request passes through the middleware layer by layer from the outside in, and a response passes through the middleware layer by layer from the inside out.

The implementation of the Onion model depends on koA-compose, and the source code for koA-compose is as follows:

'use strict'

module.exports = compose

functionCompose (middleware) {// Type determines that middleware must be an array of functionsif(! Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array! ');
  for (const fn of middleware) {
    if(typeof fn ! = ='function') throw new TypeError('Middleware must be composed of functions! '); } // return a function that takes context and next parameters. Koa calls koa-compose only to the context, so next is undefinedreturn function (context, next) {
    // last called middleware #// Initialize indexletindex = -1; // Start with the first middlewarereturn dispatch(0);
    functionDispatch (I) {// Throw an exception when a middleware next function occurs twiceif (i <= index) return Promise.reject(new Error('next() called multiple times')); // Set index to determine whether next function index = I is called multiple times in the same middleware; // Middleware functionsletFn =next (fn=undefined); fn=next (fn=undefined)if(I === middleware.length) fn = next returns a null promise object if fn is emptyif(! fn)returnPromise.resolve(); Try {// returns a promise object with a fixed value for the next middleware. // The core logic here is to recursively call the next middleware and return the return value to the previous middlewarereturn Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
      } catch (err) {
        return Promise.reject(err)
      }
    }
  }
}
Copy the code

9. Implement a Koa middleware

Middleware usually takes the following forms:

async (ctx, next) => {... }Copy the code

Generally speaking, middleware has its own configuration, so we summed up a general middleware writing method, we can pass in the configuration of the way to return customized middleware according to the configuration:

module.exports = function(options) {// Configuration processingreturnAsync (CTX, next) => {// Middleware logic... }}Copy the code

Usage:

App.use (middleware(options)) // Middleware (options) returns middlewareCopy the code

Koa-compose, mentioned in the previous interview question, can combine multiple middleware, or combine related middleware into one large middleware:

app.use(compose([middleware1, middleware2, ...] ))Copy the code

OK ~! Now let’s customize a middleware! Background: The website is often attacked by some IP addresses, affecting the normal operation of services. Therefore, a middleware is made to filter IP addresses, and all IP addresses on the IP blacklist are rejected for further processing requests.

/* ** iplimiter: IP filter middleware, for IP blacklist directly return, the request is not to continue ** ip_blacklist: Array, example: ['192.123.12.11']
*/
module.exports = function(ip_blacklist) {
  return async (ctx, next) => {
    if(Array.isArray(ip_blacklist) && ip_blacklist.length) {
      let ip = ctx.request.headers['x-real-ip'] | |' '// Obtain the client IP address. Since nginx is used as the load balancer, the method of obtaining the IP address can be through the x-real-IP fieldif(ip && ip_blacklist.indexOf(ip) ! == -1) { await next() }else {
        return res.end('ip restricted')}}else {
      await next()
    }
  }
}
Copy the code

10. Which sport did you feel played an important role in?

A little…

All around (30 min)

It is HR face all around, chatted the reason that chooses front end and the view that develops to front end, the study way at ordinary times and study method, a few competition that university campus lives, attend and activity, take an examination of grind and obtain employment a few views. Later, I got the internship offer of Byte successfully.

reflection

The interviewers are considerate and will guide you to think about the questions without ideas rather than having fun at stumping people. As for the algorithm questions, they are relatively simple on the whole and pay more attention to practical implementation and knowledge base.

The pace of the interview is also relatively fast, the three rounds of technical interviews are basically connected to the interval of 15 minutes. You can also see byte for basic knowledge is more important, knowledge base or need to see more, there are some framework source code and principle to see the words is also a lot of extra points.

The effect of the three aspects was not very ideal, but finally I successfully got the internship offer, which was relatively lucky. Also wish everyone can get the ideal offer ~

References:

Implement Generator self-execution

Learn Koa – let’s write a middleware