2021.7 huolala, shrimp skin, youzan... Interview arrangement of senior front-end post

JS related

JS prototype and prototype chain

function Person() {}
Person.prototype.name = 'Zaxlct';
Person.prototype.sayName = function() {
  alert(this.name);
}
var person1 = new Person();
//When JS creates objects, there is a__ proto__   Is used to point to the prototype object of the constructor that created it.
//Every object has  __ proto__   Property, but only function objects have   prototype   attribute
//  object   person1   There is one  __ proto__ Property and the constructor that creates it is   Person, the prototype object of the constructor is   Person.prototype
console.log(person1.__proto__ == Person.prototype) //true
//Of all function objects__ proto__ All point to Function.prototype
String.__proto__ === Function.prototype  // true
String.constructor == Function //true

prototype.jpg

Several ways of JS inheritance

Explain in detail

  1. Prototype inheritance

function Parent () {
  this.name = 'Parent'
  this.sex = 'boy'
}
function Child () {
  this.name = 'child'
}
//  Point the prototype object of the child class to an instance of the parent class
Child.prototype = new Parent()
//Excellent: inherits the template of the parent class and the prototype object of the parent class
//Missing: 1. Cannot implement multiple inheritance (because the prototype object has been specified)
//    2. When creating a subclass, you cannot pass parameters to the constructor of the parent class
  1. Constructor inheritance

Use call or apply inside the subclass constructor to call the parent constructor and copy the instance properties of the parent class to the subclass.

function Parent (name) {
  this.name = name
}
function Child () {
  //Use. call   To change   Parent   Pointer inside constructor
  Parent.call(this, 'child')
}
//Excellent: it solves the problem that the subclass instances of the prototype chain inherit and share the parent class reference object, realizes multi inheritance, and can pass parameters to the parent class when creating subclass instances
//Missing: Construction inheritance can only inherit the instance properties and methods of the parent class, not the properties and methods of the parent class prototype
  1. Combinatorial inheritance

    Composite inheritance is the combination of prototype chain inheritance and constructor inheritance.

    • Prototype chain inheritance is used to ensure that the subclass can inherit the properties and methods in the parent class prototype

    • Construct inheritance is used to ensure that the subclass can inherit the instance properties and methods of the parent class

  2. Parasitic combinatorial inheritance

  3. class inheritance

In class   Inheritance mainly depends on two things:

  • extends

  • super

class Parent {
  constructor (name) {
    this.name = name
  }
  getName () {
    console.log(this.name)
  }
}
class Child extends Parent {
  constructor (name) {
    super(name)
    this.sex = 'boy'
  }
}

Event Loop event loop

Synchronous and asynchronous, macro task and micro task are two different dimensions of function description.

Synchronization tasks refer to tasks queued on the main thread. The next task can be executed only after the previous task is executed; Asynchronous tasks refer to tasks that do not enter the main thread but enter the task queue. The task will enter the main thread for execution only after the main thread task is completed and the task queue starts to notify the main thread and request to execute the task.

After a macro task is executed, it will check whether there is a micro task queue. If yes, execute all tasks in the micro task queue first; If not, the top tasks in the macro task queue will be read in the execution environment stack; When micro tasks are encountered during macro task execution, they are added to the micro task queue in turn. After the stack is empty, read the tasks in the micro task queue again, and so on.

Promise > asynchronous (micro task (process.nextTick, Promises.then, Promise.catch, restore, reject, mutationobserver) > macro task (setTimeout, setInterval, setImmediate))

await blocking   The following code executes, so jump out of the async function to execute the next micro task

Promise and   Async/Await    difference

async/await is implemented based on Promise and looks more like synchronous code,

  • There is no need to write anonymous functions to handle the resolve value of Promise

  • Error handling: Async/Await enables try/catch to handle both synchronous and asynchronous errors.

  • Conditional statements are as concise as error handling

  • Intermediate value processing (the return value of the first method used as the second method parameter) solves the nesting problem

  • Convenient debugging

const makeRequest = () => {
    try {
        getJSON().then(result => {
            //  JSON.parse may fail
            const data = JSON.parse(result)
            console.log(data)
        })
        //  Uncomment to handle asynchronous code errors
        // .catch((err) => {
        //   console.log(err)
        // })
    } catch (err) {
        console.log(err)
    }
}

Using aync/await, catch can handle JSON.parse errors:

const makeRequest = async () => {
    try {
        // this parse may fail
        const data = JSON.parse(await getJSON())
        console.log(data)
    } catch (err) {
        console.log(err)
    }
}

promise how to realize chain call and return different states

Implement chain call: a promise object will be returned after using the. then() or. catch() method. You can continue to call with the. then() method. The parameters obtained by calling again are the contents of the previous then method return

  1. The three states of promise are   Completed / pending / rejected

  2. The status can only be pending -- > fulfilled or pending -- > rejected, and can not be modified again once it is changed;

  3. Used in Promise   resolve   and   reject   Two functions to change the state;

  4. What the then method does internally is state judgment:

  • If the status is success, the success callback function is called

  • If the status is failed, call the failed callback function

Function coritization

Currying   It is to transform the original function that receives multiple parameters into a function that accepts a single parameter (the first parameter of the original function) and returns a new function. The new function can accept the remaining parameters and return the same result as the original function.

  1. Parameter pair multiplexing

  2. Improve practicability

  3. Deferred execution only passes part of the parameters of the function to call it and let it return a function to process the remaining parameters. Coriolised functions can delay receiving parameters, that is, for example, a function needs to receive two parameters during execution, otherwise it cannot be executed. However, coriolised functions can receive one parameter first

//  Ordinary add function
function add(x, y) {
    return x + y
}

//  After Currying
function curryingAdd(x) {
    return function (y) {
        return x + y
    }
}

add(1, 2)           // 3
curryingAdd(1)(2)   // 3

JS object deep cloning

Recursively traverse the object to solve the circular reference problem

To solve the circular reference problem, we need a storage container to store the corresponding relationship between the current object and the copied object (suitable for storing with the key value data structure, that is, map) , when copying the current object, we first find out whether the storage container has copied the current object. If it has been copied, it will be returned directly. If not, it will continue to copy.

function deepClone(target) {
    const map = new Map()
    function clone (target) {
        if (isObject(target)) {
            let cloneTarget = isArray(target) ? [] : {};
            if (map.get(target)) {
                return map.get(target)
            }
            map.set(target,cloneTarget)
            for (const key in target) {
                cloneTarget[key] = clone(target[key]);
            }
            return cloneTarget;
        } else {
            return target;
        }
    }
    return clone(target)
};

JS modularization

The modules in nodeJS are implemented based on the commonJS specification. The principle is to read and write files. Exports and module.exports are used for exporting files, and require is used for importing files. Each file is a module; the code in each file will be written in a closure function by default. Amd specification is an asynchronous loading module, which allows you to specify callback functions, AMD   yes   RequireJS   The standardized output of module definition in the promotion process.

AMD advocates relying on the front,   CMD advocates dependency. For dependent modules, AMD executes in advance and CMD executes in delay.

In ES6, we can use   import   Keyword introduction module, through   exprot   Keyword export module, but ES6 cannot be executed in the browser at present, so we can only compile unsupported import into widely supported one through babel   require.

Differences between CommonJs and ES6 modularity:

  1. The CommonJS module outputs a copy of the value, and the ES6 module outputs a reference to the value.

  2. CommonJS module is loaded at run time, and ES6 module is the output interface at compile time.

Front end Modularization: CommonJS,AMD,CMD,ES6

The difference between import and require import

ES6 standard module of import; require is the introduction method of AMD specification;

import is called at compile time, so it must be placed at the beginning of the file; It is a deconstruction process, and require is a runtime call, so require can theoretically be used anywhere in the code; Is the assignment process. In fact, the result of require is an object, number, string, function, etc., and then assign the result of require to a variable

Asynchronous loading JS mode

  1. Anonymous function self-tuning dynamic creation of script tag loading js

(function(){
    var scriptEle = document.createElement("script");
    scriptEle.type = "text/javasctipt";
    scriptEle.async = true;
    scriptEle.src = "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js";
    var x = document.getElementsByTagName("head")[0];
    x.insertBefore(scriptEle, x.firstChild);  
 })();
  1. async attribute

//  The async attribute specifies that the load script will execute asynchronously once it is available
<script type="text/javascript" src="xxx.js" async="async"></script>
  1. defer attribute

//  The defer attribute specifies whether script execution is delayed until the page is loaded
<script type="text/javascript" src="xxx.js" defer="defer"></script>

Set,Map,WeakSet,WeakMap

The Set object can store any type of data. The value is unique and there are no duplicate values.

A Map object stores key value pairs, and any value can become its key or value.

WeakSet   Structure and   Set   Similarly, it is also a collection of non repeated values   WeakMap   An object is a collection of key value pairs

Different: WeakSet   Members of can only be objects, not values of other types. WeakSet is not traversable.

WeakMap only accepts objects as key names (except null), and does not accept other types of values as key names.

The object pointed to by the key name of the WeakMap is not included in the garbage collection mechanism.

call,apply

call( this,a,b,c )   After the first parameter, all subsequent parameters are the values passed into the function. apply( this,[a,b,c] )   There are only two parameters. The first is an object and the second is an array. This array is the parameter of the function.

Common: they can be used to call a method instead of another object, and change the object context of a function from the initial context to the new object specified by thisObj.

The so-called anti shake means that the function can only be executed once in n seconds after triggering the event. The so-called throttling means that the function can only be executed once in n seconds after continuously triggering the event.

What is the third parameter of addEventListener? It is captured when it is true and bubbles when it is false

Object.prototype.toString.call()   Judge object type

//  new   Set is to implement array de duplication,
//  Array.from() converts the de duplication into an array
let arr2 = Array.from(new Set(arr));

Lexical scope and scope chain

The scope specifies how to find variables, that is, to determine the access rights of the currently executing code to variables.

ES5 only has global scope and function scope, while ES6 adds block level scope

Temporary deadband: within a code block, use   let   and   const   Before the command declares a variable, the variable is unavailable, which is called a temporary deadband in syntax.

JavaScript uses lexical scope, that is, static scope.

The scope of a function is determined when the function is defined.

When searching for a variable, you will first search from the variable object of the current context. If it is not found, you will always find the variable object of the global context, that is, the global object, from the variable object of the parent execution context on the lexical level. In this way, the linked list composed of variable objects of multiple execution contexts is called the scope chain.

The new keyword does four things:

function _new(constructor, ...arg) {
//  Create an empty object
  var obj = {};
  //  The ` _proto ` of the empty object points to the ` prototype 'of the constructor,   Add properties for this new object  
  obj.__proto__ = constructor.prototype; 
  //  The scope of the constructor is assigned to the new object
  var res = constructor.apply(obj, arg); 
  //  Returns a new object. If there is no explicit return statement, this is returned
  return Object.prototype.toString.call(res) === '[object Object]' ? res : obj; 
}

Arrow functions should not be used in some cases:

  • When you want the function to be promoted (the arrow function is anonymous)

  • When you want to use this/arguments in a function, because the arrow functions themselves do not have this/arguments, they depend on the external context

  • Use named functions (arrow functions are anonymous)

  • When using function as constructor (arrow function has no constructor)

  • When you want to add a function as a property and use the object in it, because we can't access it   this   The object itself.

Four methods of judging arrays

  1. Array.isArray()   judge

  2. instanceof   Judgment: check whether the prototype attribute of the constructor appears in the prototype chain of the object and return a Boolean value. let a = []; a instanceof Array; //true

  3. Constructor judgment: constructor attribute of the instance points to constructor let a = [1,3,4]; a.constructor === Array;//true

  4. Object.prototype.toString.call()   Judge let a = [1,2,3]; object. Prototype. ToString. Call (a) = = '[object array]'; / / true

What are the advantages of TS

  1. Static input: static typing is a feature that detects errors when developers write scripts.

  2. Large development projects: Refactoring with TypeScript tools becomes easier and faster.

  3. Better collaboration: type safety is about detecting errors during coding, not when compiling a project.

  4. Greater productivity: clean ECMAScript 6 code, automatic completion and dynamic input help to improve the efficiency of developers.

Difference between interface and type

  • interface can only define object types. Type declarations can declare any type.

  • interface can declare merging, and two identical interfaces will merge. Type declaration merging will report an error

  • Type can be derived from type

Frame Vue React

What's new in Vue3.0

Bidirectional data binding Proxy

Proxy can be understood as setting an "interception" before an object. When the object is accessed, it must go through this layer of interception. This means that you can perform various operations in this layer of interception. For example, you can process the original object in this layer of interception and return the data structure you want to return.

ES6 natively provides a Proxy constructor, which is interpreted on the MDN as: the Proxy object is used to define the user-defined behavior of basic operations (such as attribute search, assignment, enumeration, function call, etc.).

const p = new Proxy(target, handler);
//target:    The target object to intercept (can be any type of object, including a native array, a function, or even another proxy)
//handler: an object that defines the behavior to be intercepted

const p = new Proxy({}, {
    get(target, propKey) {
        return 'Ha ha, you were intercepted by me';
    }
});

console.log(p.name);

For the new attributes, there is no need to add reactive processing again, because Proxy is an operation on an object. As long as you access the object, you will go to the logic of Proxy.

Vue3 Composition API

Vue3.x   Composition API setup was introduced   It is the entry to use the composition API in the component. Setup   When is the execution time   beforeCreate   Execute before

reactive, ref and toRefs, isRef

Vue3.x can use reactive and ref for data definition.

//  props   Pass in component pair properties
//  context   A context object that contains some useful attributes: attrs,parent,refs
setup(props, context) {
  //  ref   Define data
  const year = ref(0);
  //  reactive   Handle bidirectional binding of objects
  const user = reactive({ nickname: "xiaofan", age: 26, gender: "female" });
  setInterval(() => {
    year.value++;
    user.age++;
  }, 1000);
  return {
    year,
    //  Using toRefs, the structure is deconstructed
    ...toRefs(user),
  };
},
//  isRef is provided to check whether an object is a ref object

watchEffect listener function

  • watchEffect does not need to manually pass in dependencies

  • watchEffect is executed once to automatically collect dependencies

  • watchEffect cannot get the value before the change, but only the value after the change

computed can pass in get and set

Defines the calculation properties that can be changed

const plusOne = computed({
 get: () => count.value + 1,
 set: val => { count.value = val - 1 }
});

Using TypeScript and JSX

Setup now supports the return of a rendering function, which returns a JSX. JSX can directly use the reactive state declared in the setup scope:

export default {
 setup() {
 const count = ref(0);
 return () => (<div>{count.value}</div>);
 },
};

Vue versus React?

Similarities:

  1. Both have Virtual DOM (Virtual DOM is a JavaScript object that maps to the real DOM)

  2. Both provide responsive and componentized view components.

Differences: Vue is an MVVM framework with two-way data binding. When the ViewModel updates the Model, it updates to the View through data binding.

React is a one-way data flow library with state driven view. State --> View --> New State --> New View   ui = render (data)

Templates render differently. React renders templates through JSX, while Vue renders templates through extended HTML.

Component forms are different. Vue files combine HTML, JS and CSS. react provides class components and function groups

Vue encapsulates some v-if, v-for and React, which are implemented by itself with a higher degree of freedom

Vue initialization process, bidirectional data binding principle

vue.js uses data hijacking combined with publisher subscriber mode to hijack setter s, getter s and dep.addSub of various properties through Object.defineProperty() to collect subscription dependencies. The watcher monitors data changes and publishes messages to subscribers when data changes, triggering corresponding monitoring callbacks.

The listener Observer is used to hijack and listen to all properties. If there is any change, it will notify the subscriber. The subscriber Watcher can receive the change notification of the attribute and execute the corresponding function, so as to call the corresponding update to update the view.

v-model   Command, which can easily realize the two-way binding between form input and application state.

computed:   Caching is supported. Recalculation will be performed only when the dependent data result changes. Asynchronous operation is not supported. If an attribute depends on other attributes, many to one, usually calculated

watch:   When the data changes, the corresponding operation is triggered directly. Asynchronous is supported. The listening data must be the data in props declared in data or passed by the parent component. When the data changes, other operations are triggered. The function has two parameters

Implementation principle of Vue router

The core of the introduction of end-to-end routing and the implementation principle of Vue router is to update the view without re requesting the page. Switching between paths, that is, switching between components. Vue router implements single page route jump mode: hash mode and history mode. Set the mode parameter as required

hash mode: render different data of the specified DOM position according to different values through the change of anchor value. Each time # after the change, a record will be added to the browser's access history. Use the "back" button to return to the previous position. History mode: Using   window.history.pushState   API to complete URL jump without reloading the page.

Implementation principle of vuex:

Vue.use(vuex) calls vuex's install method

Before the beforeCreate hook, the vuexInit method is mixed in. The vuexInit method implements store injection into the vue component instance and registers vuex   The reference property $store of the store.

The state state of Vuex is a response form, which stores the state in the data of vue instance component with the help of vue's data;

Vuex's getters realize real-time data monitoring with the help of vue's calculated attribute.

The principle and operation mechanism of nextTick?

nextTick source code analysis

When Vue updates the DOM, it also calls nextTick internally for asynchronous queue control. Whenever data changes are observed, Vue will open a queue and buffer all data changes that occur in the same event loop. If the same watcher is triggered multiple times, it will only be pushed into the queue once.

DOM will at least update the view uniformly after all data changes in the current event loop are completed. When we call nextTick ourselves, it adds our own callback function after updating the microtask (micro task queue) of the dom,

This ensures that our code is executed after the DOM is updated, and avoids the possible multiple execution problems of setTimeout. Ensure that the micro tasks in the queue are executed before an event loop.

Vue implements a high-level component

A higher-order component is a function that takes a component as a parameter and returns a new component. Dynamically add some additional properties or behaviors to the object during program operation without changing the object itself.

//  Received by higher order component (HOC)   props   It should be transmitted to the packaged component, that is, the original component prop should be directly transmitted to the packaged component
//  High level components can be added, deleted and modified   props
export default function Console(BaseComponent) {
  return {
    props: BaseComponent.props,
    mounted() {
      console.log("High order component");
    },
    render(h) {
      console.log(this);
      //  take   this.$slots   Format as array because   h   The third parameter of the function is the child node, which is an array
      const slots = Object.keys(this.$slots)
        .reduce((arr, key) => arr.concat(this.$slots[key]), [])
        .map((vnode) => {
          vnode.context = this._self; //  Binding to high-level components, vm: solve the problem that named slots are rendered as default slots
          return vnode;
        });
 
      //  Transparent props, transparent events, transparent slots
      return h(
        BaseComponent,
        {
          on: this.$listeners,
          attrs: this.$attrs, //  attrs   Refers to those that are not declared as   props   Properties of
          props: this.$props,
        },
        slots
      );
    },
  };
}

Vue.component(),Vue.use(),this.$xxx()

The Vue.component() method registers global components.

  • The first parameter is the user-defined element name, that is, the label name of this component to be used in other components in the future.

  • The second parameter is the Vue component to be registered.

import Vue from 'vue';
//  Introducing the loading component  
import Loading from './loading.vue';
//  Register loading as a global component and use the loading component in other components through the < loading > tag
Vue.component('loading', Loading);

Vue.use registers the plug-in, which receives a parameter. This parameter must have an install method. The vue.use function calls the install method of the parameter internally.

  • If the plug-in has not been registered, an installed attribute will be added to the plug-in after successful registration, with the value of true. The Vue.use method internally detects the installed attribute of the plug-in to avoid repeated registration of the plug-in.

  • The plug-in's install method will receive two parameters. The first parameter is Vue and the second parameter is the configuration item options.

  • You can add global methods or properties inside the install method

import Vue from 'vue';

//  This plug-in must have the install method
const plugin = {
  install (Vue, options) {
    //  Add global method or attribute
    Vue.myGlobMethod = function () {};
    //  Add global directive
    Vue.directive();
    //  Add blend
    Vue.mixin();
    //  Add instance method
    Vue.prototype.$xxx = function () {};
    //  Register global components
    Vue.component()
  }
}

//  Vue.use will call the install method of plugin internally
Vue.use(plugin);

Mount the Hello method on Vue's prototype

import Vue from 'vue';
import Hello from './hello.js';
Vue.prototype.$hello = Hello;

this.$hello('hello world ') can be found in the vue component

Vue parent component transfers props data, and child component modifies parameters

  • When a parent-child component passes values, the parameters, arrays and objects passed by the parent component can be modified directly after the child component accepts them, and the corresponding values of the parent component will also be modified. A warning is issued in the console.

  • If the passed value is a string, an error will be reported if you modify it directly. One way data flow. Every time the parent component is updated, all prop s in the child component will be refreshed to the latest value.

If the sub component wants to modify the data in prop:

  1. Define a local variable and assign a value using the value of prop

  2. Define a calculation property, process the value of prop and return

Vue parent-child component lifecycle execution sequence

Load Render Pass

Parent beforecreate - > parent created - > parent beforemount - > child beforecreate - > child created - > child beforemount - > child mounted - > parent mounted

Sub component update process

Parent BeforeUpdate - > child BeforeUpdate - > child updated - > parent updated

Parent component update process

Parent BeforeUpdate - > parent updated

Destruction process

Parent beforedestroy - > child beforedestroy - > child destroyed - > parent destroyed

Vue custom directives

The custom instruction provides several hook functions: bind: called when the instruction is bound to the element for the first time, inserted: called when the bound element is inserted into the parent node, update: called when the VNode of the component is updated

After using slot, you can display the inserted new label in the subcomponent

webpack and Engineering

The life cycle of webpack, and hooks

Compiler (entire lifecycle [k) ə m ˈ pa ɪ l ə r] ) hook https://webpack.docschina.org/api/compiler-hooks/compilation (compile)[ ˌ k ɑː mp ɪˈ le ɪʃ n] ) hook

The compiler object contains all the configuration information of the webpack environment. This object is created at one time when starting the webpack, and all operable settings are configured, including options, loader and plugin. When a plug-in is applied in a webpack environment, the plug-in will receive a reference to the compiler object. You can use it to access the main environment of webpack.

The compilation object contains the current module resources, compilation generated resources, changed files, etc. When running the webpack development environment middleware, whenever a file change is detected, a new compilation will be created to generate a new set of compilation resources. The compilation object also provides many callbacks at critical times for the plug-in to choose when doing custom processing.

compiler represents the whole lifecycle of webpack from Startup to shutdown   It just represents a new compilation process

webpack compilation process

The compilation process of Webpack is a serial process. The following processes will be executed from start to end:

  1. Initialization parameters: read and merge parameters from configuration files and Shell statements to get the final parameters;

  2. Start compilation: initialize with the parameters obtained in the previous step   Compiler   Object, load all configured plug-ins, and execute object   The run method starts compiling;

  3. Determine entry: according to the in the configuration   entry   Find all the entry files;

  4. Compilation module: starting from the entry file, call all configured modules   Loader   Translate the module, find out the module that the module depends on, and then recurse this step until all the files that the entry depends on have been processed in this step;

  5. Complete module compilation: use after step 4   Loader   After translating all modules, the final translated content of each module and the dependencies between them are obtained;

  6. Output resources: according to the dependencies between entries and modules, they are assembled into chunks containing multiple modules, and then each   Chunk   Convert to a separate file and add it to the output list. This step is the last chance to modify the output content;

  7. Output completion: after determining the output content, determine the output path and file name according to the configuration, and write the file content to the file system.

Optimize the webpack packaging and compilation process of the project

1. Build management: during the build process, each Loader   and   Plugin   The execution time of is consumed on the Loader compiling JS and CSS and the plugin performing compression operation on these two types of code. A tool: speed measure webpack plugin

2. Cache: most loaders provide cache   Configuration item. cache-loader  , Write the compilation result of loader to the hard disk cache

3. Multi core compilation. The happypack project is connected to multi-core compilation, which is understood as happypack   Fill all threads with compilation work

4. Pull out, webpack DLL plugin   These static dependencies are extracted from each build logic, and the static dependencies are packaged separately. Externals removes the static resources that do not need to be packaged from the build logic and uses CDN references

5. Although tree shaking relies on a certain module, it only uses some of its functions. adopt   Tree shaking, eliminate unused modules to achieve the purpose of deleting useless code.

First screen loading optimization

Lazy loading of routes: instead, import is used as a reference, which is dynamically introduced in the form of a function. You can package the respective route files. Only when a given route is parsed can the route components be downloaded;

Element UI load on demand: reference the components actually used;

Repeated packaging of components: the Commons chunkplugin configuration is used to unpack the packages. The packages that have been used twice or more are extracted and put into the public dependency file. There are reusable components on the home page, and the public dependency file will also be downloaded;

Gzip: after unpacking, use gzip to compress and close the sourcemap.

UglifyJsPlugin:    Production environment, compress obfuscated code and remove console code

CDN deployment of static resources: when the static request is made in nginx, the address of the static resources will be obtained to redirect the CDN content distribution network

For the first screen loading of the mobile terminal, the skeleton screen can be used, the loading can be customized, and the front page can be rendered on the service terminal separately.

How to optimize front-end performance (21 optimizations + 7 positioning modes)

Web pack hot update mechanism

Hot update process summary:

  • Start the local server so that the browser can request local static resources

  • After the page is opened for the first time, the server and the client establish a communication channel through websocket to return the next hash to the front end

  • The client obtains the hash, which will be used as the hash of the next request to the server for hot-update.js and hot-update.json

  • After modifying the page code, Webpack listens to the file modification and starts compiling. After compiling, it sends a build message to the client

  • After the client obtains the hash, the client constructs a hot-update.js script link and inserts it into the main document

  • After the hot-update.js is successfully inserted, execute the createRecord and reload methods of the hotAPI, obtain the render method of the Vue component, re render the component, and then update the UI without refresh.

webpack loader and plugin are introduced. The difference between CSS loader and style loader

loader   It is A converter that compiles A file to form B file,

plugin  , It is an extender to operate files. It is aimed at the whole process of webpack packaging after the loader is completed. It does not directly operate files. It will listen to some nodes (run, build module, program) in the process of webpack packaging

Babel   It can convert the ES6/ES7 code into the code that the specified browser can support.

css-loader   The function of style loader is to transcode CSS files: use < style > to inject CSS loader internal styles into our HTML pages

First use   CSS loader transcodes and then uses it   Insert style loader into file

How to write a webpack plugin?

https://segmentfault.com/a/1190000037513682

Composition of webpack plug-in:

  • A JS named function or a class (think about the plug-ins we usually use)   new XXXPlugin())

  • Define an apply method on the prototype of the plug-in class / function.

  • Pass in the compiler in the apply function and insert the specified event hook to get the compilation object in the hook callback

  • Process specific instance data inside the webpack through compilation

  • If the plug-in is asynchronous, after the logic of the plug-in is written, call the callback provided by webpack.

Why did Vite start so fast

Webpack will package first, then start the development server, and directly give the packaging results when requesting the server.

Vite directly starts the development server and requests which module to compile the module in real time.

Vite takes the module files in the development environment as the files to be executed by the browser, rather than packaging and merging them like Webpack.

Since Vite does not need to be packaged at startup, it means that there is no need to analyze module dependencies and compile. Therefore, the startup speed is very fast. When the browser requests a module, it compiles the module content as needed.

How is your scaffold made

use   download-git-repo   Download the warehouse code democommander: complete   node.js   Command line solution. Declare the program using. option()   Method to define the option Inquirer.js: a collection of command-line user interfaces.

Front end monitoring

Front end monitoring usually includes behavior monitoring (PV/UV, buried point interface statistics), anomaly monitoring and performance monitoring.

A monitoring system can be roughly divided into four stages: log collection, log storage, statistics and analysis, reporting and warning.

Error monitoring

Vue special error warning method   Vue.config.errorHandler, (Vue provides functions that can only capture the page life cycle, such as created and mounted)

Vue.config.errorHandler = function (err) {
console.error('Vue.error',err.stack)
//  Logical processing
};

Framework: betterjs, fundebug (charge) the script for capturing errors should be placed at the front to ensure that error information can be collected. Methods:

  1. Window. Oneror() when js runtime error triggers, oneror can accept multiple parameters (message, source, lineno, colno, error).

  2. window.addEventListener('error'), function(e) {}, true   It will be triggered before window.oneror. It cannot prevent the execution of the default event handler function, but it can catch the error of resource loading exception globally

Front end JS error capture -- sourceMap

How to monitor web page crashes** What's the difference between collapse and carton** Monitoring error

  1. The Service Worker has its own independent working thread, which is different from the web page. When the web page crashes, the Service Worker will not crash under normal circumstances;

  2. The life cycle of service workers is generally longer than that of web pages, which can be used to monitor the status of web pages;

    Caton: rendering is blocked while loading

Performance monitoring & & Performance Optimization

Performance index:

  • FP (first drawing)

  • FCP (First contentful paint)

  • LCP (maximum content paint time)

  • FPS (frames transmitted per second)

  • TTI (page interactive Time to Interactive)

  • HTTP   Request response time

  • DNS   Resolution time

  • TCP   Connection time

Performance data collection requires   window.performance API  ,   JS Library   web-vitals: import {getLCP} from 'web-vitals';

    //  Redirection time
    redirect: timing.redirectEnd - timing.redirectStart,
    //  DOM   Rendering time
    dom: timing.domComplete - timing.domLoading,
    //  Page load time
    load: timing.loadEventEnd - timing.navigationStart,
    //  Page unload time
    unload: timing.unloadEventEnd - timing.unloadEventStart,
    //  Request time
    request: timing.responseEnd - timing.requestStart,
    //  Current time when getting performance information
    time: new Date().getTime(),
    //  DNS query time consuming
    domainLookupEnd - domainLookupStart
 //  TCP link time consuming
    connectEnd - connectStart
 //  request time consuming
    responseEnd - responseStart
 //  Parsing dom trees takes time
    domComplete - domInteractive
 //  White screen time
    domloadng - fetchStart
 //  onload time
    loadEventEnd - fetchStart

Common means of performance optimization: caching technology   Preloading technology   Rendering scheme.

  1. cache  : It mainly includes cdn, browser cache, local cache and application offline package

  2. Preload  : prefetch is another performance optimization technique. Pre fetching can tell browser users what resources they may use in the future.

  • prefetch supports pre fetching images, scripts or any resources that can be cached by the browser.

    Add in head  < linkrel="prefetch"href="image.png">

  • prerender is a heavyweight option that allows the browser to load all resources of a specified page in advance.

  • subresource can be used to specify that resources have the highest priority. The current page needs or will be used soon.

  1. Rendering scheme:

    • Static rendering (SR)

    • Front end rendering (CSR)

    • Server side rendering (SSR)

    • Client side rendering (NSR): NSR data request, first screen data request and data online are paralleled with an initialization framework of webview and JS initialization, which greatly shortens the first screen time.

640.png

Six common design patterns and application scenarios

https://www.cnblogs.com/whu-2017/p/9471670.html

The concept of observer model

Observer mode is a kind of behavioral mode. It defines a one to many dependency, allowing multiple observer objects to listen to a topic object at the same time. When the state of this subject object changes, it will notify all observer objects.

Concept of publishing subscriber pattern

In the publish subscribe mode, the sender of a message is called publishers, and the message will not be sent directly to a specific receiver, called subscribers. It means that publishers and subscribers do not know each other's existence. A third-party component, called information mediation, is needed. It connects subscribers and publishers. It filters and distributes all incoming messages. In other words, the publish subscribe model is used to handle the exchange of information between different system components, even if these components do not know each other's existence.

You need a third-party component, called information mediation, that connects subscribers and publishers

Factory mode    It mainly provides an interface for creating objects. Scenario: it is impossible to foresee what kind of instances need to be created during coding.

Agent mode command mode

Singleton mode

Ensure that a class has only one instance and provide a global access point to access it. (window)

Http and browser related

Seven layer network model

Application layer, presentation layer, session layer, transport layer, network layer, data link layer and physical layer

TCP: connection oriented, reliable transmission (ensuring data correctness and data order), used to transmit a large amount of data (stream mode), slow speed, and requires a lot of overhead (time and system resources) to establish a connection. (application scenario: HTP, HTTP, mail)

UDP: non connection oriented, unreliable transmission, used to transmit a small amount of data (packet mode), fast speed and possible packet loss (application scenario: instant messaging)

Connected     Connection oriented     Non connection oriented
 Transmission reliability   reliable        unreliable
 Application occasion    A small amount of data    Transmit large amounts of data

https

The client first asks the server for the public key, and then encrypts the information with the public key. After the server receives the ciphertext, it decrypts it with its own private key. The server public key is placed in the digital certificate.

url to load the whole process of rendering

  1. DNS domain name resolution.

  2. TCP shakes hands three times to establish connection.

  3. Send HTTP request message.

  4. The server processes the request and returns the response message.

  5. The browser parses the rendered page.

  6. Wave four times and disconnect.

The DNS protocol provides the ability to find IP addresses through domain names, or vice versa   IP address anti query domain name service. DNS is a network server. Our domain name resolution is simply to record an information record on DNS.

TCP handshakes three times and waves four times: handshakes and waves are initiated by the client, and the client ends. Three handshakes and four waves

Load balancing: before entering the real application server, the request may pass through the machine responsible for load balancing. Its function is to reasonably distribute the request to multiple servers and forward HTTP requests; At the same time, it has anti attack and other functions. It can be divided into DNS load balancing, HTTP load balancing, IP load balancing, link layer load balancing, etc.

Web Server: after the previous load balancing, the request will enter the Web Server on the corresponding server, such as   Apache,Tomcat

Reverse proxy works on HTTP, generally   Nginx. Visiting baidu.com all over the country must be accessed through an agent. It is impossible to visit Baidu's server.   (VPN forward proxy, proxy client)

Browser parsing and rendering process: after the returned html is transferred to the browser, if there is gzip, it will be decompressed first to find out the file coding format. The HTML loaded by the external chain resources will be parsed from top to bottom. In case of js, CSS will stop parsing and rendering until js execution is completed. Parse HTML, build DOM tree, parse CSS, generate CSS rule tree, merge DOM tree and CSS rules, and generate render tree to render

The behavior of changing the DOM tree, page layout, and element style is called redrawing

The behavior that causes changes in DOM tree structure and page layout is called reflow

GUI rendering thread is responsible for rendering HTML elements of browser interface. When the interface needs   Repaint   Or caused by some operation   Reflow   When, the thread executes. When the JavaScript engine runs the script, the GUI rendering thread is suspended, that is, it is "frozen". It will not be executed until the JS program is completed. Therefore, if JS is executed for too long, the rendering of the page will be inconsistent, resulting in the feeling of page rendering loading blocking. JavaScript can manipulate DOM. If the interface is rendered while modifying these element attributes, the element data may be inconsistent before and after rendering

GPU draws multi process browsers: master process, plug-in process, GPU, tab page (browser kernel) multi-threaded browser kernel: each tab page can be regarded as a browser kernel process, and then the process is multi-threaded.

It has several types of sub threads:

  • GUI thread

  • JS engine thread

  • Event triggered thread

  • Timer thread

  • HTTP request thread

http1 and HTTP2

http2

Multiplexing: multiple requests with the same domain name share the same TCP connection, reducing latency

Request priority: set the priority for each request

Binary transmission; It was transmitted in plain text

Data flow: packets are not sent in sequence, and packets are marked. All packets of each request or response become a data stream,

Server push: you can actively send messages to the client.

Header compression: reduce the size and number of packets

If a request is blocked in the pipeline transmission in HTTP/1.1, all requests behind the queue are blocked. HTTP/2 multiple requests reuse a TCP connection. Once packet loss occurs, all HTTP requests will be blocked. HTTP/3 changed the TCP protocol under HTTP to   UDP! http1 keep alive serial transmission

What is the role of keep alive in http

Set in response header   keep-alive   You can send multiple http over a TCP connection   request

Browser cache policy

Strong cache: cache control; no-cache max-age=<10000000>; expires; The priority of cache control is higher than expires;

The fields controlling forced caching are Expires and cache control respectively. If the time of the client is less than the value of Expires, the cached results will be used directly.

Negotiation cache: last modified / if modified since and Etag / if none match. The priority of Etag / if none match is higher than that of last modified / first request. The server will add the last modified field in the returned response header to indicate the last modified time of the resource.

When the browser requests again, the if modified since field will be brought in the request header. If the two fields are the same, it proves that the resource has not been modified and returns 304. Otherwise, it returns the resource again with the status code of 200;

Garbage collection mechanism:

Mark clearing: variables entering the execution environment are marked, and then after execution, these marks and variables are cleared. Check whether the variable is referenced.

Reference count: the number of times each value is referenced will be recorded. When the number of references becomes 0, it will be released.

Front end security

Homology strategy: if the protocol, domain name and port of two URL s are the same, we call them homologous. Because the browser has cookies.

  • XSS: cross site scripting   input, textarea and other areas where text information may be input, input < script SRC = "http: / / malicious website" > < / script >, and the submitted information will be stored in the server.

  • CSRF: Cross Site Request Forgery. Entice users to open the hacker's website. In the hacker's website, cross site requests are initiated by using the user's login status.

    SRC of img of site A = the request interface of site B, which can be accessed; Solution: the referer carries the request source

    After accessing the page, the form is submitted automatically, simulating a post operation and sending a post request

    Solution: the back end injects a random string into the Cookie, and the front end requests to take out the random string and add it to the back end.

  • http hijacking: hijacking by telecom operators

  • SQL injection

  • Click hijacking: entice the user to click the seemingly harmless button (actually click the transparent button)   Button in iframe), add a field to the back-end request header   X-Frame-Options

  • File upload vulnerability  : The server did not verify the uploaded file

CSS and HTML

What are BFC (block level formatting context), IFC (inline formatting context), FFC (elastic box model)

BFC (Block formatting context), i.e. block level formatting context, is an independent rendering area on the HTML page. Only the elements in the area participate in the rendering and will not affect its external elements. In short, BFC can be regarded as a "Besieged City". External elements cannot enter and internal elements cannot go out (do not interfere with each other).

A container that determines how to render elements. Rendering rules:

  • 1. The internal block level elements are placed vertically, one by one.

  • 2. The vertical distance of block level elements is determined by margin. The margins of two adjacent block level elements belonging to the same BFC will overlap.

  • 3. For left to right formatting, the left edge of each element (block level element and inline element) contacts the left edge of the containing block (the opposite for right to left formatting). This is true even if there is a float in the elements in the containing block, unless the elements in it regenerate into a BFC.

  • 4. The area of the BFC does not overlap the floating element.

  • 5. BFC is an isolated independent container. The child elements inside the container and the elements outside the container do not affect each other.

  • 6. When calculating the height of BFC container, floating elements also participate in the calculation.

Conditions for forming BFC:

1. Floating elements, float values other than none;

2. position (absolute, fixed);

3. display is one of the following values: inline block, table cell, table caption;

4. overflow values other than visible (hidden, auto, scroll);

BFC is generally used to solve the following problems

  • Margin overlap problem

  • Eliminate floating problems

  • Adaptive layout problem

flex: 0 1 auto;   What do you mean?

The element is sized according to its width and height. It shortens itself to adapt   flex   Container, but does not elongate and absorb   flex   Additional free space in the container to accommodate   flex   container  . The horizontal main axis and vertical cross axis attributes determine which axis to arrange

  • flex-grow:   0    A unitless number (): it will be treated as the value of < flex growth >.

  • flex-shrink:   one    A valid * * width * * value: it will be treated as  < The value of flex basis >.

  • flex-basis:   auto    Keyword none, auto, or initial

Zoom in, zoom out, and the spindle space occupied before allocating excess space.

Avoid CSS global pollution

  1. scoped attribute

  2. css in js

const styles = {
  bar: {
    backgroundColor: '#000'
  }
}
const example = (props)=>{
  <div style={styles.bar} />
}
  1. CSS Modules

  2. Use less to minimize the use of global pair selectors

//  Remember to write on the selector so as not to pollute all the li below ul
ul{
  >li{
    color: red;
  }
}

CSS Modules

Ruan Yifeng CSS Modules

CSS Modules is a process in a build step. The process of building tools to make the specified class reach the scope.

CSS Modules   It is allowed to declare a global rule using the syntax of:: global(.className). Any class declared in this way will not be compiled into hash string local(className): handle the localIdentName rule and compile the unique hash class name.

CSS Modules features:

  • Instead of using a selector, use only the class name to define the style

  • Instead of cascading multiple classes, use only one class to define all styles

  • Do not nest class es

Box model and   box-sizing   attribute

width: 160px; padding: 20px; border: 8px solid orange; Standard box sizing:   content-box;   Total width of element = 160 + 202 + 82; IE   Border box: total width 160

When margin/padding takes the value of percentage, it is based on the width and height of the parent element.

css drawing triangle

  1. Processing by border

//  border   handle
.class {
    width: 0;
    height: 0;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-bottom: 100px solid red;
}
//  Width height + border
div {
    width: 50px;
    height: 50px;
    border: 2px solid orange;
}
  1. Clip path clipping

div{
 clip-path: polygon(0 100%, 50% 0, 100% 100%);
}
  1. Implementation of gradient linear gradient

div {
  width: 200px;
  height: 200px;
  background:linear-gradient(to bottom right, #fff 0%, #fff 49.9%, rgba(148,88,255,1) 50%,rgba(185,88,255,1) 100%);
}

How to add shadows to triangles after CSS implements triangles

???

N implementations of CSS two column layout

Two column layouts are divided into two types, one is fixed width on the left and adaptive on the right, and the other is adaptive on both columns (that is, the width on the left is determined by sub elements, and the remaining space is supplemented on the right).

  1. How to realize left fixed width and right adaptation

//  Both elements set dislpay: inline block
.left {
    display: inline-block;
    width: 100px;
    height: 200px;
    background-color: red;
    vertical-align: top;
}
.right {
    display: inline-block;
    width: calc(100% - 100px);
    height: 400px;
    background-color: blue;
    vertical-align: top;
}
//  The two elements are set to float, and the adaptive element width on the right is calculated using the calc function
.left{
    float: left;
    width: 100px;
    height: 200px;
    background-color: red;
}
.right{
    float: left;
    width: calc(100% - 100px);
    height: 400px;
    background-color: blue;
}
//  The parent element is set to display: flex, and the adaptive element is set to flex: 1
.box{
    height: 600px;
    width: 100%;
    display: flex;
}
.left{
    width: 100px;
    height: 200px;
    background-color: red;
}
.right{
    flex: 1;
    height: 400px;
    background-color: blue;
}
//  The parent element is relatively positioned, the left element is absolutely positioned, and the margin left value set for the right adaptive element is greater than the width of the fixed width element
.left{
    position: absolute;
    width: 100px;
    height: 200px;
    background-color: red;
}
.right{
    margin-left: 100px;
    height: 400px;
    background-color: blue;
}
  1. The left and right elements are adaptive

//  flex layout   ditto
//  Set display: grid for parent element;   grid-template-columns:auto   1fr; (this attribute defines the column width. The auto keyword indicates that the length is determined by the browser itself. FR is a relative size unit, indicating that the remaining space is divided equally.) grid gap: 20px (row spacing)
.parent{
    display:grid;
    grid-template-columns:auto 1fr;
    grid-gap:20px
} 
.left{
    background-color: red;
    height: 200px;
}
.right{
    height:300px;
    background-color: blue;
}
//  Float + BFC     The parent element is set to overflow:hidden, the left fixed width element is floating, and the right adaptive element is set to overflow:auto to create BFC
.box{
    height: 600px;
    width: 100%;
    overflow: hidden;
}
.left{
    float: left;
    width: 100px;
    height: 200px;
    background-color: red;
}
.right{
    overflow: auto;
    height: 400px;
    background-color: blue;
}

CSS three column layout

  1. Float layout: left float, right float, middle margin: 0 100px;

  2. Position layout: left: 0; Right: 0; Middle left: 100px; right: 100px;

  3. Table layout: parent element display: table; Left and right width: 100px; Three elements display: table cell;

  4. Flexible layout: parent element display: flex; Left and right width: 100px;

  5. Grid layout:

//  Gird provides   The gird template columns and grid template rows properties let us set the height and width of rows and columns
.div{
    width: 100%;
    display: grid;
    grid-template-rows: 100px;
    grid-template-columns: 300px auto 300px;
}

Common scenarios and problems

How do app and H5 communicate and interact?

//  Compatible with IOS and Android
callMobile(parameters,messageHandlerName) {
  //handlerInterface is injected from iOS addScriptMessageHandler and andorid addjavascript interface code.
  if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
    // alert('ios')
    window.webkit.messageHandlers[messageHandlerName].postMessage(JSON.stringify(parameters))
  } else {
    //  alert('android ')
    //Android can't transfer js   json object, only string can be transferred
    window.webkit[messageHandlerName](JSON.stringify(parameters))
  }
}

app injects native methods into window for js to call

messageHandlerName   Agreed communication method parameters   Parameters to be passed in

Mobile terminal adaptation scheme

rem is the font size relative to the root element of HTML and em relative to the parent element. VW,VH   High score ratio of screen width to height

//Calculated according to the width diagram,   1rem  =  100px;
(function (win, doc) {
   function changeSize() {
     doc.documentElement.style.fontSize = doc.documentElement.clientWidth / 3.75 + 'px';
    console.log(100 * doc.documentElement.clientWidht / 3.75)
   }
   changeSize();
   win.addEventListener('resize', changeSize, false);

})(window, document);

Code programming related

Implement publish and subscribe

/* Pubsub */
function Pubsub(){
  //Store events and corresponding processing methods
  this.handles = {};
}

Pubsub.prototype = {
  //Pass in event type and event handling handle
  on: function (type, handle) {
    if(!this.handles[type]){
      this.handles[type] = [];
    }
    this.handles[type].push(handle);
  },
  emit: function () {
    //Get event type by passing in parameters
    //Convert arguments to a true array
    var type = Array.prototype.shift.call(arguments);
    if(!this.handles[type]){
      return false;
    }
    for (var i = 0; i < this.handles[type].length; i++) {
      var handle = this.handles[type][i];
      //Execution event
      handle.apply(this, arguments);
    }
  },
  off: function (type, handle) {
    handles = this.handles[type];
    if(handles){
      if(!handle){
        handles.length = 0;//Empty array
      }else{
      for (var i = 0; i < handles.length; i++) {
        var _handle = handles[i];
        if(_handle === handle){
          //Remove from array
          handles.splice(i,1);
        }
      }
    }
  }  
}

promise how to realize chain call and return different states

// MyPromise.js

//  First define three constants to represent the state
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

//  newly build   MyPromise   class
class MyPromise {
  constructor(executor){
    //  executor   It is an actuator, which will be executed immediately after entering
    //  And pass in the resolve and reject methods
    executor(this.resolve, this.reject)
  }

  //  Storage state variable, the initial value is   pending
  status = PENDING;

  // Why do resolve and reject use arrow functions?
  //  If called directly, the normal function this points to window or undefined
  //  Use the arrow function to make this point to the current instance object
  //  Value after success
  value = null;
  //  Reasons after failure
  reason = null;

  //  Status after successful change
  resolve = (value) => {
    //  Status modification can only be performed if the status is wait
    if (this.status === PENDING) {
      //  Status changed to success
      this.status = FULFILLED;
      //  Value after successful saving
      this.value = value;
    }
  }

  //  Change status after failure
  reject = (reason) => {
    //  Status modification can only be performed if the status is wait
    if (this.status === PENDING) {
      //  Status success to failure
      this.status = REJECTED;
      //  Reason after saving failure
      this.reason = reason;
    }
  }

    then(onFulfilled, onRejected) {
    //  Judgment state
    if (this.status === FULFILLED) {
      //  The callback is called successfully and the value is returned
      onFulfilled(this.value);
    } else if (this.status === REJECTED) {
      //  Call the failed callback and return the reason
      onRejected(this.reason);
    }
  }

}

Implement Promise.all

// Promise.all
function all(promises) {
  let len = promises.length, res = []
  if (len) {
    return new Promise(function (resolve, reject) {
        for(let i=0; i < len; i++){
            let promise = promises[i];
            promise.then(response => {
                res[i] = response

                //  When the returned result is the last one
                if (res.length === len) {
                    resolve(res)
                }

            }, error => {
                reject(error)
            })

        }
    })
}

Object array to tree array

> take entries according to level convert to result data structure

const entries = [
    {
        "province": "Zhejiang", "city": "Hangzhou", "name": "West Lake"
    }, {
        "province": "Sichuan", "city": "Chengdu", "name": "Jinli"
    }, {
        "province": "Sichuan", "city": "Chengdu", "name": "Fang Suo"
    }, {
        "province": "Sichuan", "city": "ABA", "name": "jiuzhaigou"
    }
];
 
const level = ["province", "city", "name"];

const  result = [
 {
  value:'Zhejiang',
  children:[
   {
    value:'Hangzhou',
    children:[
     {
      value:'West Lake'
     }
    ]
   }
  ]
 },
 {
  value:'Sichuan',
  children:[
   {
    value:'Chengdu',
    children:[
     {
      value:'Jinli'
     },
     {
      value:'Fang Suo'
     }
    ]
   },
   {
    value:'ABA',
    children:[
     {
      value:'jiuzhaigou'
     }
    ]
   }
  ]
 },
]

Idea: involving tree array, recursive traversal is adopted

function transfrom(list, level) {
  const res = [];
  list.forEach(item => {
    pushItem(res, item, 0);
  });

  function pushItem(arr, obj, i) {
    const o = {
      value: obj[level[i]],
      children: [],
    };
    //  Judge whether the value in the passed in array is equal to the item to be passed in
    const hasItem = arr.find(el => el.value === obj[level[i]]);
    let nowArr;
    if(hasItem) {
      //  If yes, the children of the passed in item will be traversed next time
      nowArr = hasItem.children;
    }else{
      //  non-existent   Press in arr to traverse the children passed in this item next time
      arr.push(o);
      nowArr = o.children;
    }
    if(i === level.length - 1) delete o.children;
    i++;
    if(i < level.length) {
      //  Recursive traversal
      pushItem(nowArr, obj, i);
    }
  }
}

transfrom(entries, level);

Native implementation of JS instanceof method

Simple usage

function Fn () {}
const fn = new Fn()
fn instanceof Fn  // true

The implementation is as follows:

// left instanceof right
function _instanceof(left, right) {
  //  Constructor prototype
  const prototype = right.prototype
  //  Real column object property that points to its constructor prototype
  left = left.__proto__
  //  Verify prototype chain
  while (true) {
    //  If it is null, it indicates that the prototype chain has found the top layer, and the true return is false
    if (left === null) {
      return false
    }
    //  Prototype found
    if (prototype === left){
      return true
    }
    //  Continue looking up
    left = left.__proto__
  }
}

const str = "abc"
_instanceof(str, String) // true

Programming problem

Merge arrays with the same elements

//  For example:
const arr = [
    ['a', 'b', 'c'],
    ['a', 'd'],
    ['d', 'e'],
    ['f', 'g'],
    ['h', 'g'],
    ['i']
]
//  The returned result after running is:
[
    ['a', 'b', 'c', 'd', 'e'],
    ['f', 'g', 'h'],
    ['i']
]
//  Idea 1:
const arr = [['a', 'b', 'c'], ['a', 'd'], ['d', 'e'], ['f', 'g'], ['h', 'g'], ['i']]
function transform(arr){
    let res = []
    arr = arr.map(el => el.sort()).sort()
    const item = arr.reduce((pre, cur) => {
      if (cur.some(el => pre && pre.includes(el))) {
        pre = pre.concat(cur)
      } else {
        res.push(pre)
        pre = cur
      }
      return [...new Set(pre)]
    })
    res.push(item)
    return res;
}
transform(arr)
// console.log(transform(arr));

//  Idea 2:  

function r (arr) {
  const map = new Map()
  arr.forEach((array, index) => {
    const findAlp = array.find((v) => map.get(v))
    if (findAlp) {
      const set = map.get(findAlp)
      array.forEach((alp) => {
        set.add(alp)
        const findAlp2 = map.get(alp)
        if (findAlp2 && findAlp2 !== set) {
          for(const v of findAlp2.values()){
            set.add(v)
            map.set(v, set)
          }
        }
        map.set(alp, set)
      })
    } else {
      const set = new Set(arr[index])
      array.forEach((alp) => map.set(alp, set))
    }
  })
  const set = new Set()
  const ret = []
  for (const [key, value] of map.entries()) {
    if (set.has(value)) continue
    set.add(value)
    ret.push([...value])
  }
  return ret
}

Tags: Javascript node.js Interview

Posted on Tue, 05 Oct 2021 16:25:45 -0400 by boon_chong