Hello, everyone. I am a front-end trainee who has been practicing for one and a half years. I like singing, dancing, rap and coding. This article is the author of more than a year of front-end basic knowledge of the summary and thinking, these topics are a summary of their own, for everyone is also a little meager information, I hope to bring you some help and inspiration. Written process has been a lot of big guy’s help, in this Thanks to Kay’s booklet, god three students front daily question and many never met friends, let me sprout new also have the opportunity to learn from others in the wealth of predecessors, Thanks to (· ω ·) Blue

This article summarizes the front-end basics for the reader from the following eleven dimensions

JS based

1. How to implement LET in ES5 environment

What is the difference between let and var? For this question, we can directly look at the results before and after Babel conversion and see how variables defined by let solve the problem of variable promotion in the loop

(function(){
  for(var i = 0; i < 5; i ++){
    console.log(i)  // 0 1 2 3 4
  }
})();

console.log(i)      // Uncaught ReferenceError: i is not defined
Copy the code

Var/let/const var/let/const

  • varThe declared variable will be attached to the window, andletandconstDon’t
  • varThe declared variable has a variable promotion, whileletandconstDon’t
  • letandconstDeclarations form block scopes and can only be accessed within the block scope, not across blocks or functions
  • In the same scopeletandconstCannot declare variables of the same name, whilevarcan
  • A temporary dead zone,letandconstDeclared variables cannot be used before they are declared

Babel’s transformation actually only achieves points 2, 3, and 5


2. How to implement const in ES5

The key to implementing const is the Object.defineProperty() API, which is used to add or modify attributes to an Object. You can precisely control property behavior by configuring property descriptors. Object.defineproperty () takes three arguments:

Object.defineProperty(obj, prop, desc)

parameter instructions
obj The object on which attributes are to be defined
prop The name of the property to define or modify
descriptor The property descriptor to be defined or modified


Attribute descriptor instructions The default value
value The value corresponding to this property. It can be any valid JavaScript value (numeric value, object, function, etc.). The default value is undefined undefined
get A method that provides a getter for a property, undefined if there is no getter undefined
set A method that provides a setter for a property, undefined if there is no setter. This method is triggered when the property value is modified undefined
writable Value can be changed by the assignment operator if and only if the writable of the property is true. The default is false false
enumerable Enumerable defines whether an object’s property can be considered in a for… Are enumerated in the in loop and object.keys () false
Configurable The 64x feature indicates whether the attributes of the object can be deleted, and whether any other features other than the value and writable feature can be modified false

Const cannot be modified by setting the writable property

function _const(key, value) {    
    const desc = {        
        value,        
        writable: false    
    }    
    Object.defineProperty(window, key, desc)
}
    
_const('obj', {a: 1})   / / define obj
obj.b = 2               // Obj attributes can be assigned normally
obj = {}                // Cannot assign a new object
Copy the code

Resources: How do I implement a const in ES5?

3. Write a call ()

The call() method invokes a function syntax with a specified this value and one or more arguments given separately: function.call(thisArg, arg1, arg2…)

The principle of call() is relatively simple. Since the function’s this points to its direct caller, we change the caller to complete the change this points to:

// Change the function caller example
function foo() {
    console.log(this.name)
}

/ / test
const obj = {
    name: 'Write code like CAI Xu Zheng'
}
obj.foo = foo   // Change the caller to foo
obj.foo()       // 'Write code like CAI Xucong'
Copy the code

Based on these principles, we can implement call() in two lines of code

Function.prototype.myCall = function(thisArg, ... args) {
    thisArg.fn = this              // This refers to the call object, that is, we want to change the function this refers to
    returnthisArg.fn(... args)// Execute the function and return its execution result
}
Copy the code

But we have some details to work out:

Function.prototype.myCall = function(thisArg, ... args) {
    const fn = Symbol('fn')        // Declare a unique Symbol property to prevent fn from overwriting existing properties
    thisArg = thisArg || window    // If this is not passed, the window object is bound by default
    thisArg[fn] = this              // This refers to the call object, that is, we want to change the function this refers to
    constresult = thisArg[fn](... args)// Execute the current function
    delete thisArg[fn]              // Delete the fn property we declared
    return result                  // Returns the result of the function execution
}

/ / test
foo.myCall(obj)     // output 'write code like CAI Xu Cheng'
Copy the code


4. Write the apply ()

The apply() method calls a function with a given this value and the arguments supplied as an array (or array-like object). Syntax: func.apply(thisArg, [argsArray])

Apply () is similar to call(), except that call() receives a list of parameters, while apply() receives an array of parameters, so we can simply change the input form of call() implementation

Function.prototype.myApply = function(thisArg, args) {
    const fn = Symbol('fn')        // Declare a unique Symbol property to prevent fn from overwriting existing properties
    thisArg = thisArg || window    // If this is not passed, the window object is bound by default
    thisArg[fn] = this              // This refers to the call object, that is, we want to change the function this refers to
    constresult = thisArg[fn](... args)// Execute the current function (note here: even though apply() accepts an array, the array of parameters is expanded when the original function is called. In contrast to native apply(), the function receives an expanded array of arguments.
    delete thisArg[fn]              // Delete the fn property we declared
    return result                  // Returns the result of the function execution
}

/ / test
foo.myApply(obj, [])     // output 'write code like CAI Xu Cheng'
Copy the code


5. Write a bind ()

The bind() method creates a new function, and when bind() is called, this of the new function is specified as the first argument to bind(), and the remaining arguments will be used as arguments to the new function. Syntax: function.bind(thisArg, arg1, arg2…)

Call /apply implements bind() as a function:

Function.prototype.myBind = function(thisArg, ... args) {
    return (a)= > {
        this.apply(thisArg, args)
    }
}
Copy the code

But three things are missing:

  1. Bind () takes arguments in addition to this, and the function that bind() returns also takes arguments. Both parts of the argument are passed to the returned function
  2. New changes this reference: If the bind function is new, this reference changes to refer to the instance of the current function
  3. Properties and methods of the original function are not preserved in the prototype chain
Function.prototype.myBind = function (thisArg, ... args) {
    var self = this
    // New priority
    var fbound = function () {
        self.apply(this instanceof self ? this : thisArg, args.concat(Array.prototype.slice.call(arguments)))}// Inherits properties and methods from the stereotype
    fbound.prototype = Object.create(self.prototype);

    return fbound;
}

/ / test
const obj = { name: 'Write code like CAI Xu Zheng' }
function foo() {
    console.log(this.name)
    console.log(arguments)
}

foo.myBind(obj, 'a'.'b'.'c') ()// write code like CAI Xucheng ['a', 'b', 'c']
Copy the code


6. Write a shaker function

Both anti-shake and throttling concepts are relatively simple, so we won’t waste too much space on “what is anti-shake throttling?”

Stabilization, that is, in a short period of time a large number of trigger the same event, will only perform a function, the principle to set a timer, agreed in xx milliseconds after the trigger event handling, every time the triggering event will reset the timer, xx milliseconds until no second operation, being often used in the search box/scroll bar listening event handling, if you don’t do stabilization, Event processing is triggered every time you type a word/scroll, resulting in wasted performance.

function debounce(func, wait) {
    let timeout = null
    return function() {
        let context = this
        let args = arguments
        if (timeout) clearTimeout(timeout)
        timeout = setTimeout((a)= > {
            func.apply(context, args)
        }, wait)
    }
}
Copy the code


Write a throttling function

Stabilization is delayed, and the throttle is executive, interval function throttling is executed once every once in a while, to realize the principle to set a timer, convention xx milliseconds after the event, if the time is up, so the executive function and reset the timer, and if the difference is that if each trigger reset timer, and throttling after timer to time to clear the timer

function throttle(func, wait) {
    let timeout = null
    return function() {
        let context = this
        let args = arguments
        if(! timeout) { timeout = setTimeout((a)= > {
                timeout = null
                func.apply(context, args)
            }, wait)
        }

    }
}
Copy the code

Implementation method 2: Use two timestamps prev old timestamp and now new timestamp, each trigger event will judge the time difference between the two, if the specified time is reached, execute the function and reset the old timestamp

function throttle(func, wait) {
    var prev = 0;
    return function() {
        let now = Date.now();
        let context = this;
        let args = arguments;
        if(now - prev > wait) { func.apply(context, args); prev = now; }}}Copy the code


8. Array flattening

How do we flatten a multi-layer nested array like [1, [1,2], [1,2,3] into a one-dimensional array like [1, 1,2, 2,3] :

1. ES6 flat ()

const arr = [1[1.2], [1.2.3]]
arr.flat(Infinity)  // [1, 1, 2, 1, 2, 3]
Copy the code

2. Regex after serialization

const arr = [1[1.2], [1.2.3]]
const str = ` [The ${JSON.stringify(arr).replace(/(\[|\])/g.' ')}] `
JSON.parse(str)   // [1, 1, 2, 1, 2, 3]
Copy the code

Recursion is the most direct way to deal with tree-structured data

const arr = [1[1.2], [1.2.3]]
function flat(arr) {
  let result = []
  for (const item of arr) {
    item instanceof Array ? result = result.concat(flat(item)) : result.push(item)
  }
  return result
}

flat(arr) // [1, 1, 2, 1, 2, 3]
Copy the code

4. The reduce () recursion

const arr = [1[1.2], [1.2.3]]
function flat(arr) {
  return arr.reduce((prev, cur) = > {
    return prev.concat(cur instanceof Array ? flat(cur) : cur)
  }, [])
}

flat(arr)  // [1, 1, 2, 1, 2, 3]
Copy the code

5. Iteration + expansion operator

[1, 1, 2, 1, 2, 3, [4,4,4]]
// then arr.some checks if there is an array in the array because [4,4,4] is present, and continues the second loop to merge
let arr = [1[1.2], [1.2.3[4.4.4]]]
while (arr.some(Array.isArray)) { arr = [].concat(... arr); }console.log(arr)  // [1, 1, 2, 1, 3, 4, 4, 4]
Copy the code


9. Make a Promise by hand

Implement a compliance Promise length is longer, suggested reading an article on the author: asynchronous programming two or three things | Promise/async/Generator principle analysis | 9 k


JS object oriented

Everything is an object in JS, but JS is not a true object-oriented (OOP) language because it lacks the concept of class. While ES6 introduces class and extends, it makes it easy to implement classes and inheritance. However, JS does not exist real classes, JS classes are simulated by function and prototype chain mechanism, this section will explore how to use function and prototype chain in ES5 environment to achieve the object-oriented characteristics of JS

Before we begin, let’s review the prototype chain mechanism on which subsequent implementations such as new and inheritance are based. A lot of information about the prototype chain can be written in thousands of words, but I don’t think readers need to think of the prototype chain too complicated, easy to get involved, in fact, in my opinion, the core of the prototype chain just need to remember three points:

  1. Every object has it__proto__ properties, this property refers to its prototype object. When calling the methods and properties of the instance, if they are not found on the instance object, they will look for the prototype object
  2. constructionalThe prototype propertyAlso points to the prototype object of the instance
  3. Archetypal objectThe constructor propertyPointing constructor

1. Simulate implementation of new

So the first thing we need to know is what does New do

  1. Create a new object and inherit its constructor’s prototype. This step is to inherit properties and methods from the constructor’s prototype
  2. The constructor is executed, and this inside the method is specified as the new instance. This step is used to perform the assignment inside the constructor
  3. Returns a new instance (the specification states that an object is returned if the constructor returns it, otherwise the new object created in the first step is returned)
New Foo(args) <=> myNew(args)
function myNew(foo, ... args) {
  // Create a new object and inherit the constructor's prototype property. This step is to attach obj to the prototype chain, equivalent to obj.__proto__ = foo.prototype
  let obj = Object.create(foo.prototype)  
  
  // Execute the constructor and bind a new this to it. This step is to enable the constructor to do things like this.name = name
  let result = foo.apply(obj, args)

  // If the constructor already returns an object, it returns that object, otherwise it returns a new object created by myNew. (Normally, the constructor does not return a new instance, but the consumer can choose to return a new instance to override the object created by new.)
  return Object.prototype.toString.call(result) === '[object Object]' ? result : obj
}

/ / test:
function Foo(name) {
  this.name = name
}
const newObj = myNew(Foo, 'zhangsan')
console.log(newObj)                 // Foo {name: "zhangsan"}
console.log(newObj instanceof Foo)  // true
Copy the code


2. How does ES5 implement inheritance

When it comes to inheritance, one of the most obvious things to think about is the extends of ES6. Of course, it’s not a good idea to just answer this question. Let’s implement inheritance from a function and prototype chain perspective

One. Prototype chain inheritance

The principle of prototype chain inheritance is very simple, directly let the prototype object of the subclass point to the parent class instance, when the subclass instance can not find the corresponding attributes and methods, it will look for its prototype object, that is, the parent class instance, so as to achieve the inheritance of the attributes and methods of the parent class

/ / parent class
function Parent() {
    this.name = 'Write code like CAI Xu Zheng'
}
// The prototype method of the parent class
Parent.prototype.getName = function() {
    return this.name
}
/ / subclass
function Child() {}

// Make the subclass's prototype object point to the parent instance, so that properties and methods not found in the Child instance are found on the prototype
Child.prototype = new Parent()
Child.prototype.constructor = Child // Bind Constructor as per the rules of the prototype chain. This step does not affect inheritance, but is required when constructor is used

// The Child instance can then access the name attribute and getName() method on the parent class and its prototype
const child = new Child()
child.name          // 'Write code like CAI Xucong'
child.getName()     // 'Write code like CAI Xucong'
Copy the code

Disadvantages of stereotype inheritance:

  1. Because all Child instance prototypes point to the same Parent instance, changes to the Parent reference type variable of one Child instance affect all Child instances
  2. Cannot pass arguments to the parent class construct when creating a subclass instance, i.e., no implementationsuper()The function of the
/ / sample:
function Parent() {
    this.name = ['Write code like CAI Xu Zheng'] 
}
Parent.prototype.getName = function() {
    return this.name
}
function Child() {}

Child.prototype = new Parent()
Child.prototype.constructor = Child 

/ / test
const child1 = new Child()
const child2 = new Child()
child1.name[0] = 'foo'
console.log(child1.name)          // ['foo']
console.log(child2.name)          // ['foo'] (expected to be [' write code like CAI '], changes to child1.name cause all child instances to change)
Copy the code

Constructor inheritance

Constructor inheritance, that is, execute the constructor of the parent class in the constructor of the child class and bind this to it. Let the parent class constructor attach member attributes and methods to this of the child class. This can not only avoid sharing a prototype instance between instances, but also pass parameters to the parent class constructor

function Parent(name) {
    this.name = [name]
}
Parent.prototype.getName = function() {
    return this.name
}
function Child() {
    Parent.call(this.'zhangsan')   // Execute the superclass constructor and bind the subclass's this so that attributes in the superclass can be assigned to the subclass's this
}

/ / test
const child1 = new Child()
const child2 = new Child()
child1.name[0] = 'foo'
console.log(child1.name)          // ['foo']
console.log(child2.name)          // ['zhangsan']
child2.getName()                  GetName () cannot be found. The constructor inherits properties and methods from the parent stereotype
Copy the code

Disadvantages of constructor inheritance:

  1. Attributes and methods cannot be inherited from the superclass stereotype

Three. Combinatorial inheritance

Since both stereotype chain inheritance and constructor inheritance have complementary advantages and disadvantages, why not combine them so that we have composite inheritance that combines the two

function Parent(name) {
    this.name = [name]
}
Parent.prototype.getName = function() {
    return this.name
}
function Child() {
    // Constructor inheritance
    Parent.call(this.'zhangsan')}// Prototype chain inheritance
Child.prototype = new Parent()
Child.prototype.constructor = Child

/ / test
const child1 = new Child()
const child2 = new Child()
child1.name[0] = 'foo'
console.log(child1.name)          // ['foo']
console.log(child2.name)          // ['zhangsan']
child2.getName()                  // ['zhangsan']
Copy the code

Disadvantages of combinatorial inheritance:

  1. The constructor is executed twice each time a subclass instance is created.Parent.call()andnew Parent()), although this does not affect inheritance from the parent class, it is not elegant to create instances of subclasses with two copies of the same properties and methods in the stereotype

4. Parasitic combinatorial inheritance

To solve the problem of the constructor being executed twice, we change the point to superclass instance to point to the superclass prototype, minus one constructor execution

function Parent(name) {
    this.name = [name]
}
Parent.prototype.getName = function() {
    return this.name
}
function Child() {
    // Constructor inheritance
    Parent.call(this.'zhangsan')}// Prototype chain inheritance
// Child.prototype = new Parent()
Child.prototype = Parent.prototype  // Change 'point to parent instance' to 'point to parent prototype'
Child.prototype.constructor = Child

/ / test
const child1 = new Child()
const child2 = new Child()
child1.name[0] = 'foo'
console.log(child1.name)          // ['foo']
console.log(child2.name)          // ['zhangsan']
child2.getName()                  // ['zhangsan']
Copy the code

There is a problem with this approach, however. Since the subclass prototype and the parent prototype point to the same object, we can affect the parent prototype by adding a getName() method to child.prototype. This will cause Parent. Prototype to add or override a getName() method as well. To fix this, we’ll make a shallow copy of Parent

function Parent(name) {
    this.name = [name]
}
Parent.prototype.getName = function() {
    return this.name
}
function Child() {
    // Constructor inheritance
    Parent.call(this.'zhangsan')}// Prototype chain inheritance
// Child.prototype = new Parent()
Child.prototype = Object.create(Parent.prototype)  // Change 'point to parent instance' to 'point to parent prototype'
Child.prototype.constructor = Child

/ / test
const child = new Child()
const parent = new Parent()
child.getName()                  // ['zhangsan']
parent.getName()                 // Error: getName() not found
Copy the code

So far, we have completed the implementation of inheritance in ES5 environment. This inheritance method is called parasitic combinatorial inheritance, which is the most mature inheritance method at present. Babel’s transformation of ES6 inheritance also uses parasitic combinatorial inheritance

We review the implementation process: first prototype chain is the most easy to think of inheritance, by dividing the subclass instance prototype points to the parent class to inherit properties and methods of the parent, but the prototype chain of the defects in the inheritance the inheritance of the subclass instance reference type changes will affect all instances of the objects, and can’t to the parent class constructor arguments. Therefore, we introduced constructor inheritance, which gets the attributes and methods of the parent class by calling the parent constructor in the subclass constructor and passing in the subclass this. However, constructor inheritance also has a defect. Constructor inheritance cannot inherit the attributes and methods on the parent class prototype chain. So we integrated the advantages of two kinds of inheritance, put forward the combined inheritance, but also introduces a new combined hierarchy problems, it is time to create a subclass instances are performed twice the superclass constructor, we will through the subclass prototype points to the parent class instance to subclass prototype to shallow copy of the parent class prototype to solve this problem, the parasitic, finally realizes the modular inheritance


V8 engine mechanics

1. How does V8 execute a piece of JS code

  1. Preparsing: Checks for syntax errors but does not generate an AST
  2. Generate AST: Generate abstract syntax tree after lexical/syntax analysis
  3. Generate bytecode: The baseline compiler (Ignition) converts the AST to bytecode
  4. Generating machine code: The Turbofan converts bytecode into optimized machine code, and if a code is frequently executed during line-by-line bytecode execution, V8 converts that code directly to machine code and saves it for the next execution without passing bytecode, optimizing execution speed

The above points are a minimal summary of the V8 implementation mechanism, and I recommend reading resources:

1. How does V8 run – V8’s JavaScript execution pipeline 2

2. Introduce reference counting and tag clearing

  • Reference count: If you assign a reference type to a variable, the number of references to the object is +1. If the variable changes to some other value, the number of references to the object is -1. The garbage collector collects the object with the number of references to 0. However, when objects are referenced repeatedly, the number of references will never return to zero, resulting in memory cannot be freed.
  • Tag cleanup: The garbage collector marks all objects in memory and then walks from the root node, removing the tags of referenced objects and objects in the runtime environment. The remaining tagged objects are unreachable objects waiting to be collected.

3. How does V8 recycle garbage

In the JS engine, variables are stored in two main locations: stack memory and heap memory. Stack memory stores basic type data and memory address of reference type data, and heap memory stores reference type data

Stack memory collection:

Stack memory is reclaimed after the stack context is switched, which is relatively simple

Heap memory collection:

The V8 heap memory is divided into the new generation memory and the old generation memory. The new generation memory is temporarily allocated memory, which lasts for a short time, while the old generation memory lasts for a long time

  • New generation memory reclamation mechanism:
    • The new generation has a small memory capacity, only 32MB on 64-bit systems. The memory of the new generation is divided into From and To. When garbage collection is carried out, the From is scanned first, the non-viable objects are reclaimed, the viable objects are sequentially copied To To, and then the From/To is replaced, waiting for the next collection
  • Old generation memory reclamation mechanism
    • Promotion: If a new generation variable survives multiple collections, it will be put into the old generation memory
    • Tag cleanup: Old-generation memory iterates through and marks all objects, then unmarks objects that are in use or strongly referenced, and reclaims tagged objects
    • Defragment: Move objects to one end of memory

Resources: Talk about V8 engine garbage collection

4. Why is JS slower than C++ and what are the optimizations made in V8

  1. JS problem:
    • Dynamic typing: causes the type to be checked every time a property/method is accessed; Dynamic typing is also difficult to optimize at compile time
    • Attribute access: in C++/Java and other languages, methods and attributes are stored in the array and can be obtained only by array displacement, while JS is stored in the object and hash query is required for each acquisition
  2. V8 optimization:
    • Optimized JIT(just-in-time compilation) : compared to compiled languages such as C++/Java, JS is less efficient when interpreted as it executes. V8 optimizes this process: if a piece of code is executed multiple times, V8 will convert the code to machine code and cache it for the next run.
    • Hidden classes: for languages like C++, it takes only a few instructions to get variable information through offsets, while JS requires string matching, which is inefficient. V8 borrowed the idea of classes and offset positions and divided objects into different groups, namely hidden classes
    • Embedded cache: Cache the results of object queries. The inline cache is the cache of the results of the normal query process: get the address of the hidden class -> find the offset value based on the attribute name -> calculate the address of the attribute
    • Garbage collection management: described above

Resources: Why is the V8 so fast?


Browser rendering mechanism

1. How does the browser render

  1. The HTML and CSS are parsed separately to generate a DOM tree and a CSSOM tree
  2. Merge into render tree
  3. Layout according to render tree
  4. Finally, GPU is invoked to draw and display on the screen

2. How to speed up the first screen according to the browser rendering mechanism

  1. Optimize file size: Loading and parsing of HTML and CSS blocks rendering tree generation, which can affect the first screen speed, so optimize file size and reduce CSS file hierarchy to speed up the first screen speed
  2. Avoid resource downloads blocking document parsingThe <script> tag is parsed by the browser and blocks parsing of the document until the script is executed, so we usually place the <script> tag at the bottom or add it to itDefer, asyncFor asynchronous downloads

3. What is backflow (rearrangement) and under what circumstances can backflow be triggered

  • When the size or position of an element changes, the render tree needs to be recalculated. This is called backflow
  • Geometric attributes of DOM elements (width/height/padding/margin/border) triggers backflow when changes occur
  • A DOM element movement or increment triggers backflow
  • Read and writeoffset/scroll/clientWill trigger backflow
  • callwindow.getComputedStyleIt triggers backflow.

4. What is repainting and under what circumstances will repainting be triggered

  • DOM style changes that do not affect the geometry of the DOM trigger redraw, not backflow. Redraw performs better than reflux because the DOM location information does not need to be updated, eliminating the layout process

5. What is GPU acceleration, how to use it, and its disadvantages

  • Advantages: When using properties such as transform, opacity, and filters, the processing will be completed directly on the GPU, and the change of these properties will not cause backflow redrawing
  • Cons: GPU rendering fonts can cause font blurriness, and excessive GPU processing can cause memory problems

6. How can backflow be reduced

  • useclassalternativestyleReduce the use of style
  • useResize, scrollIs treated with anti-shake and throttling, both of which directly cause backflow
  • usevisibilityreplacedisplay: noneBecause the former will only cause redrawing and the latter will cause backflow
  • When modifying elements in batches, you can take them out of the document stream and then put them in the document stream when the changes are complete
  • Avoid triggering the synchronous layout event we are fetchingoffsetWidthWhen the value of this type of attribute, you can use variables to store the query result, avoiding multiple queries, each timeoffset/scroll/clientWill trigger backflow when queried
  • For complex animation effects, use absolute positioning to keep them out of the document stream. Complex animation effects frequently trigger backflow repainting. We can use absolute positioning to keep animation elements out of the document stream to avoid backflow repainting.

Resources: Browser rendering mechanisms you must understand


Browser Cache policy

1. Describe the location and priority of the browser cache

  1. Service Worker
  2. Memory Cache
  3. Disk Cache
  4. Push Cache
  5. None of the above caches will make a network request

2. Describe the differences between caches

  1. Service Worker

Similar to a Web Worker, it is a separate thread in which we can cache files and read them when the main thread needs them. A Service Worker gives us the freedom to choose which files to cache and their matching and reading rules, and the cache is persistent

  1. Memory Cache

The memory cache, the memory cache is not persistent, the cache will be freed as the process is freed

  1. Disk Cache

Disk cache, which is more persistent and larger than memory cache, determines which resources need to be cached based on HTTP header fields

  1. Push Cache

Push cache is HTTP/2 content, currently less used

3. This section describes the browser cache policy

Strong cache (don’t ask the server for cache)

Set Expires

  • Expiration time, for example"Expires: Thu, 26 Dec 2019 10:30:42 GMT"Indicates that the cache will expire after this time. The expiration date is an absolute date. If the local date is changed or the local date is inconsistent with the server date, the cache expiration time will be incorrect.

Sets the cache-control

  • HTTP/1.1 new field, cache-control can passmax-ageField to set the expiration time, for example"Cache-control: Max - age = 3600"Cache-control can also be setprivate/no-cacheAnd other fields

Negotiate the cache (you need to ask the server if the cache has expired)

Last-Modified

  • The last modification time, the first time the browser requests a resource, is appended to the server’s responseLast-ModifiedWhen the browser requests the resource again, it will include it in the request headerIf-Modified-SinceThe value of the field is the Last Modified time returned by the server. The server compares the two times and returns 304 if they are the same. Otherwise, the new resource is returned and last-Modified is updated

ETag

  • HTTP/1.1 new field, indicating the unique identifier of the file, as long as the file content changes, the ETag will be recalculated. The caching process is the same as last-Modified: the server sends the ETag field -> the browser sends if-none-match when it requests again -> If the ETag value does not Match, the file has changed, returns a new resource and updates the ETag, and returns 304 If it matches

Both comparisons

  • ETag is more accurate than last-Modified: if we open a file and do not modify it, last-Modified also changes, and last-Modified takes one second. If the file is Modified in one second, it still hits the cache
  • If no cache policy is set, then the browser takes 10% of the Date minus last-Modified value in the response header as the cache time

Resources: Anatomy of the browser cache mechanism


Network related

1. Talk about the OSI seven-layer model of the network. Which layer are TCP/IP and HTTP located at

model An overview of the unit
The physical layer A connected medium, such as a network cable or cable, in which data is transmitted in bits bit
Data link layer The data link layer encapsulates bits into data frames and delivers them frame
The network layer Define IP addresses, define routing capabilities, and establish host-to-host communication The packet
The transport layer Responsible for reliable or unreliable transfer of data, establish port to port communication Data segment
The session layer Control the ability to talk between applications and distinguish between different processes
The presentation layer Data format identification, basic compression encryption function
The application layer Various applications


2. Common HTTP status codes

Start of 2xx (request successful)

200 OK: The request sent by the client to the server is processed and returned


Start with 3xx (redirection)

301 Moved Permanently: Permanently redirected, the requested page has been Permanently Moved to a new location. When the server returns this response, the requester is automatically forwarded to a new location

302 Moved Permanently: Temporarily redirected, the requested page has been temporarily Moved to a new location. The server currently responds to requests from web pages in different locations, but the requester should continue to use the original location for future requests

The requested page has Not been Modified since the last request. When the server returns this response, the web page content is not returned


Start with 4XX (client error)

400 Bad Request: indicates an incorrect Request. The server does not understand the syntax of the Request

401 Unauthorized: The request to be sent requires HTTP authentication information. This option is common when the client is not logged in

403 Forbidden: The server rejects requests, which is common when the client has insufficient permissions

404 Not Found: The server could Not find the resource


5xx (server error)

500 Inter Server Error: Indicates an internal Error. The Server encounters an Error and cannot complete the request

Implemented: The server is Not equipped to fulfill requests

502 Bad Gateway: An invalid response is received from the upstream server when the server working as a Gateway or proxy tries to execute the request.

503 Service Unavailable: The service is unavailable. The server is currently unavailable (it is overloaded or down for maintenance). It’s usually a temporary state.


3. What is the difference between a GET request and a POST request

Standard answer:

  • GET request parameters are placed in the URL, and POST request parameters are placed in the request body
  • The length of GET request parameters is limited, and the length of POST request parameters can be very large
  • A POST request is slightly more secure than a GET request because the parameters of a GET request are in the URL and have a history
  • GET requests can be cached, but POST requests cannot

One step further:

In fact, HTTP protocol does not require GET/POST request parameters must be placed in the URL or request body, nor does it specify the length of GET request. Currently, the length of URL is limited by various browsers. The fundamental difference between GET and POST is that GET requests are idempotent, while POST requests are not

Idempotent means that one or more requests for a resource have the same side effects. For example, search is an idempotent operation, while delete and add are not.

Because GET requests are idempotent, they may be repeated in a poor network environment, resulting in the risk of repeated operations on data. Therefore, GET requests are used for operations with no side effects (such as search), and POST is suitable for new/delete operations

Resources: HTTP | GET and POST? Most of the answers online are wrong


4. What are the components of an HTTP request packet

An HTTP request packet consists of four parts: request line, header, blank line, and request data

5. HTTP common request/response headers and their meanings

Common headers (headers that both request and response headers have)

field role value
Cache-Control Control the cache Public: indicates that the response can be cached by any object (including client/proxy server)

Private (default) : The response can only be cached by a single client, not by a proxy server

No-cache: The cache is verified by the server. Before using the cache, the browser compares the ETag. If the ETag is unchanged, 304 is returned and the cache is used

No-store: disables any cache
Connection Whether persistent connections are required (HTTP 1.1 default) keep-alive / close
Transfer-Encoding Transmission code format of the packet body Chunked (chunked)/Identity (uncompressed and modified)/gzip(LZ77)/compress(LZW)/deflate(zlib)

Request header

field role grammar
Accept Tells the (server) what type of content the client can process Text/HTML, image/*, */*
If-Modified-Since willLast-ModifiedIs sent to the server to ask if the resource has expired (been modified), returns a new resource if it has expired, or 304 if it has not Example: if-modified-since: Wed, 21 Oct 2015 07:28:00 GMT
If-Unmodified-Since willLast-ModifiedIs sent to the server to ask if the file has been modified, or 200 if not, or 412 preprocessing error, which can be used for resumable breakpoints. Popular point saidIf-Unmodified-SinceIf the file is not modified,If-Modified-SinceIt is downloaded when the file is modified Example: if-unmodified-since: Wed, 21 Oct 2015 07:28:00 GMT
If-None-Match willETagIs sent to the server to ask if the resource has expired (been modified), returns a new resource if it has expired, or 304 if it has not Example: if-none-match: “bfc13a6472992d82d”
If-Match willETagIs sent to the server to ask if the file has been modified, or 200 if not, or 412 preprocessing error, which can be used for resumable breakpoints Example: if-match: “bfc129c88CA92d82d”
Range Tell the server which part of the file to return for breakpoint continuation Example: Range: bytes=200-1000, 2000-6576, 19000-
Host Specifies the domain name of the server (for virtual hosts) and, optionally, the TCP port number on which the server listens Example: Host:www.baidu.com
User-Agent Tells the HTTP server the name and version of the operating system and browser used by the client User-Agent: Mozilla/<version> (<system-information>) <platform> (<platform-details>) <extensions>

Response headers

field role grammar
Location The address to which the page needs to be redirected. It is generally meaningful in the response code 3xx Location: <url>
ETag The identifier for a particular version of the resource. If the content has not changed, the Web server does not need to send a complete response ETag: “<etag_value>”
Server Information about the software used by the source server to process the request Server: <product>

Entity header (use headers for the entity portion of request and response messages)

field role grammar
Allow Resources can support HTTP request methods Allow: <http-methods>, for example: Allow: GET, POST, HEAD
Last-Modified The last modification time of a resource, used as a validator to determine whether received or stored resources are consistent with each other, is less accurate than ETag Example: Last-Modified: Wed, 21 Oct 2020 07:28:00 GMT
Expires Response expiration time Expires: <http-date>. Example: Expires: Wed, 21 Oct 2020 07:28:00 GMT

Of course, there are more than a few HTTP headers, but in order to avoid forgetting too much (I didn’t bother to read the others), here are some common, detailed documents that can be viewed in MDN


6. What is the difference between HTTP/1.0 and HTTP/1.1

  • Long connection: HTTP/1.1 supports the pipeline of long connections and requests. Multiple HTTP requests can be sent over a TCP connection, avoiding the time consumption and delay caused by establishing TCP connections for multiple times
  • Cache processing:HTTP / 1.1 introducedEntity Tag, if-unmodified-since, if-match, if-none-matchTo control the cache, see the browser Cache section
  • Bandwidth optimization and network connection usage: HTTP1.1 introduces the range header in the request header to support breakpoint continuation
  • Host header processing: in HTTP/1.0, each server has a unique IP address, but with the development of virtual Host technology, multiple hosts share an IP address is increasingly common, HTTP1.1 request message and response messages should support the Host header field, and the request message if there is no Host header field will be 400 errors


7. Introduce the new HTTP/2.0 features

  • Multiplexing: The simultaneous completion of multiple requests over a SINGLE TCP connection
  • Server push: The server can actively push resources to the client
  • New binary format: HTTP/2 transmits data in binary format, which is more analytical and extensible than HTTP/1.1’s text format
  • Header compression: HTTP/2 compresses the header, reducing the size of the transmitted data


8. Talk about the fundamentals of HTTP/2.0 multiplexing and the problems it solves

HTTP/2 addresses the same problem HTTP/1.1 has:

  • TCP slow start: After the TCP connection is established, it will go through a slow start and then fast send process, just like the start of a car. If our webpage files (HTML/JS/CSS/icon) all go through a slow start, the performance is not a small loss. In addition, slow start is a TCP policy to reduce network congestion, which we cannot change.
  • Multiple TCP connections compete for bandwidth: Multiple TCP connections compete for bandwidth when the bandwidth is insufficient, affecting the download of key resources.
  • HTTP/1.1 queue header blocking: Although HTTP/1.1 long links can transmit multiple requests over a TCP connection, only one request can be processed at a time, and other requests can be blocked until the current request is completed.

To solve these problems, HTTP/2 uses only one TCP long connection per domain name to transfer data, and requests are directly parallel and non-blocking, which is multiplexing

Implementation principle: HTTP/2 introduces a binary frame splitting layer. When the client and server transmit data, the data will be processed by the binary frame splitting layer first and converted into frames with request ID one by one. These frames are combined into corresponding data according to THE ID after transmission.


9. Tell me about HTTP / 3.0

Although HTTP/2 solves many of the problems of 1.1, HTTP/2 still has some defects. These defects are not from HTTP/2 itself, but from the underlying TCP protocol. We know that TCP links are reliable connections. HTTP/1.1 can use up to six TCP connections at the same time, with one blocking and the other five still working, but HTTP/2 has only one TCP connection, which magnifies the blocking problem.

Because TCP protocol has been widely used, it is difficult to modify TCP directly. Based on this, HTTP/3 chooses a compromise method — UDP protocol. HTTP/2 implements multiplexing, 0-RTT, TLS encryption, traffic control, packet loss and retransmission on the basis of UDP.


Http0.9, http1.0, http1.1, http2, http3


10. What is the difference between HTTP and HTTPS

  • HTTPS uses port 443, while HTTP uses 80
  • HTTPS requires a certificate
  • HTTP is hypertext transfer protocol, is plaintext transfer; HTTPS is the ssl-encrypted protocol, which is more secure for transmission
  • HTTPS is slower than HTTP because HTTPS adds nine packets for the SSL handshake in addition to the three packets for the TCP handshake

11. How is HTTPS encrypted

We understand HTTPS encryption and why it is used by analyzing several encryption methods, step by step:

Symmetric encryption

The client and server share a secret key to encrypt and decrypt messages, which is called symmetric encryption. The client and server agree on an encrypted key. The client encrypts the message with the key before sending it. After sending the message to the server, the server decrypts the message with the key.

Asymmetric encryption

When asymmetric encryption is used, both the client and the server have a public key and a private key. Only the private key can decrypt the contents encrypted by the public key. Keep the private key and send the public key to the other party. In this way, before sending a message, encrypt it with the public key of the other party, and decrypt it with its own private key after receiving it. In this way, an attacker cannot decrypt the contents of a transmission even if he only gets the public key in the transmission

Tampering with the public key

Third Party authentication

The weakness of the above method is that the client does not know whether the public key is returned by the server or the middleman, so we introduce a third party authentication: Namely a third party to use our own public key private key encryption, the browser has built-in some authoritative third-party certification body’s public key, the browser will use the third party’s public key to unlock encrypted private key by a third party of our own public key, so as to obtain the public key, if can successful decryption, means that access to your public key is correct

However, third-party authentication cannot completely solve the problem. Third-party authentication is for everyone, and the middleman can apply for the certificate. If the middleman replaces the original certificate with his own certificate, the client cannot confirm the authenticity of the public key

A digital signature

To enable the client to verify the source of the public key, a digital signature is added to the public key. The digital signature is a one-way hash generated from various information, such as the enterprise and website, and the public key. Once the information forming the digital signature changes, the hash value changes, which constitutes a unique identification of the source of the public key.

To be specific, the server generates a pair of keys locally and then applies for a digital certificate with the CA(third-party authentication center) with various information, such as the public key, enterprise and website. The CA uses a one-way hash algorithm (such as MD5) to generate a string of abstracts, which is the unique identifier of the information. The CA then encrypts the digest using its own private key and sends it to us along with the public key of our own server.

After obtaining the digital signature, the browser uses the built-in CA public key of the browser to unlock the digital certificate and verify it to obtain the correct public key. Asymmetric encryption has low performance. After obtaining the public key, the client randomly generates a symmetric key, uses the public key to encrypt the key, and sends the key to the server. The server uses its private key to unlock the symmetric key, and then performs symmetric encryption on subsequent encrypted connections.

To sum up, HTTPS uses asymmetric encryption, third-party authentication, and digital signature to obtain the correct public key during authentication. After obtaining the correct public key, HTTPS communicates in symmetric encryption

Resources: See pictures to learn HTTPS


The front security

What is a CSRF attack

CSRF stands for Cross-site Request Forgery, which is an attack method to induce users to perform unintentional operations on the currently logged Web application.

If a hacker places an external link of another website on his own site, such as “www.weibo.com/api, by default, the browser will visit this site with weibo.com cookies. If the user has logged in to the site and the site is not protected against CSRF attacks, The server will assume that the user is calling the interface and performing the operation, causing the account to be hijacked.

How do I defend against CSRF attacks

  • validationToken: When the browser requests the server, the server returns a token. Each request is considered a valid request only after it contains both the token and cookie
  • validationRefererVerify the source site by verifying the Referer of the request header, which is easy to forge
  • Set up theSameSite: Sets the SameSite for cookies so that cookies are not issued with cross-domain requests, but browsers are not compatible

What is an XSS attack

XSS stands for Cross Site Scripting, which is designed to enable users to load and execute malicious web applications by injecting malicious command code into web pages, exploiting vulnerabilities left in web development. For example, JS code is implanted in the comment area, and the code is executed when the user enters the comment page, resulting in the page is implanted with advertisements and the account information is stolen

What are the types of XSS attacks

  • Stored: Attacks are stored on the server. The attack script is inserted in the comment area. If the attack script is stored on the server, all users who see the corresponding comment are attacked.
  • Reflection type: The attacker mixes the script in the URL. The server receives the URL and takes out the malicious code as a parameter, splices it into HTML and returns it. The browser parses the HTML and executes the malicious code
  • DOM type: The attack script is written in the URL to induce the user to click the URL. If the URL is parsed, the attack script will be run. The main difference is that DOM attacks do not go through the server

How do I defend against XSS attacks

  • Input inspection: For the input<script><iframe>Such labels are escaped or filtered
  • Set httpOnly: Many XSS attacks are aimed at stealing user cookies to forge identity authentication. Setting this property prevents JS from obtaining cookies
  • Enabling CSP, that is, enabling the whitelist, prevents the loading and running of resources that are not on the whitelist


Sorting algorithm

1. Handwritten bubble sort

Bubble sort is probably the first sort that a lot of people are going to encounter, but it’s a little bit easier, so I won’t go into that

function bubbleSort(arr){
  for(let i = 0; i < arr.length; i++) {
    for(let j = 0; j < arr.length - i - 1; j++) {
      if(arr[j] > arr[j+1]) {
        let temp = arr[j]
        arr[j] = arr[j+1]
        arr[j+1] = temp
      }
    }
  }
  return arr
}
Copy the code


2. How to optimize a bubble sort

Bubble sort always executes (n-1)+(n-2)+(n-3)+.. +2+1, but if the sorting has already been completed or the input is an ordered array, then the following comparison will be unnecessary. To avoid this situation, we add a flag to check whether the sorting has been completed in the middle (i.e. whether the element swap has occurred).

function bubbleSort(arr){
  for(let i = 0; i < arr.length; i++) {
  let flag = true
    for(let j = 0; j < arr.length - i - 1; j++) {
      if(arr[j] > arr[j+1]) {
        flag = false
        let temp = arr[j]
        arr[j] = arr[j+1]
        arr[j+1] = temp
      }
    }
    // The meaning of this flag is: if 'a loop' does not swap elements, it means that the sorting is complete
    if(flag)break;
  }
  return arr
}
Copy the code


3. Handwritten quicksort

Basic steps of fast sorting:

  1. Select the base element
  2. Elements smaller than the base element go to the left, and elements larger go to the right
  3. Repeat step one and two in the left and right subarrays until there is only one element left
  4. Merge arrays step by step up
function quickSort(arr) {
    if(arr.length <= 1) return arr          // Recursive termination condition
    const pivot = arr.length / 2 | 0        / / reference point
    const pivotValue = arr.splice(pivot, 1) [0]
    const leftArr = []
    const rightArr = []
    arr.forEach(val= > {
        val > pivotValue ? rightArr.push(val) : leftArr.push(val)
    })
    return [ ...quickSort(leftArr), pivotValue, ...quickSort(rightArr)]
}
Copy the code


4. How to optimize a quicksort

In situ sorting

If we open two arrays each time, we will consume a lot of memory space. If we open two arrays each time, we will run out of memory. We should avoid opening new memory space, i.e. finish sorting in place

Instead of opening a new array, we swap elements directly on the original array at each partition, moving the elements less than the base number to the beginning of the array, as in [5,1,4,2,3] :

Code implementation:

function quickSort(arr, left, right) {          // Left and right represent the interval subscripts of "new array" after partition. Since there is no new array, we need left/right to confirm the position of the new array
    if (left < right) {
        let pos = left - 1                      //pos is the "replaced position", the first trip is -1
        for(let i = left; i <= right; i++) {    // Loop through the array, replacing the elements
            let pivot = arr[right]              // Select the last bit of the array as the base number,
            if(arr[i] <= pivot) {               // if less than or equal to the base number, pos++, and transpose elements, use less than or equal to instead of less than, in order to avoid the endless loop due to repeated data
                pos++
                let temp = arr[pos]
                arr[pos] = arr[i]
                arr[i] = temp
            }
        }
        // After the sorting is complete, the pos position is the base position, and the array is split by the pos position
        quickSort(arr, left, pos - 1)        
        quickSort(arr, pos + 1, right)
    }
    return arr      // The recursion terminates when the array contains only 1 or 0 elements (left>=right)
}

/ / use
var arr = [5.1.4.2.3]
var start = 0;
var end = arr.length - 1;
quickSort(arr, start, end)
Copy the code

This interchange process takes some time to digest. For more details, see Quicksort.

Three way fast row

The above quick sorting is not optimization, should be said to be quick sorting correction writing method, in fact, there are two problems we can optimize:

  1. Case of ordered array: If the input array is ordered and the datum is taken sequentially, it may cause the subarray on the datum side to remain empty, reducing the time complexity to O(n2).
  2. A situation where a large amount of duplicate data is used: For example, the input data is,2,2,2,2,3 [1], no matter the reference point is 1, 2 or 3, the size of the array on both sides of the reference point will be unbalanced, affecting the efficiency of fast exhausting

To the first question, we can be a reference point in randomized to solve, for your second question, we can use the three quick ways to optimize, for example, for the above,2,2,2,2,3 [1], we take 2 basis points, at the time of partition, the array element is divided into 2 | 2 | less than 2 3 area, The part equal to the reference point will not enter the next sorting, which greatly improves the efficiency of fast platoon

5. Handwritten merge sort

Merge sort and quicksort are similar in idea, both are recursive divide and conquer, the difference is that quicksort partition and quicksort sort, and merge will be sorted after the partition is complete

function mergeSort(arr) {
    if(arr.length <= 1) return arr		// The recursion terminates when one element is left
    const midIndex = arr.length/2 | 0
    const leftArr = arr.slice(0, midIndex)
    const rightArr = arr.slice(midIndex, arr.length)
    return merge(mergeSort(leftArr), mergeSort(rightArr))	// Divide first, merge later
}

/ / merge
function merge(leftArr, rightArr) {
    const result = []
    while(leftArr.length && rightArr.length) {
    	leftArr[0] <= rightArr[0]? result.push(leftArr.shift()) : result.push(rightArr.shift()) }while(leftArr.length) result.push(leftArr.shift())
    while(rightArr.length) result.push(rightArr.shift())
    return result
}
Copy the code

6. Handwritten heap sort

A heap is a special tree. As long as the tree is a complete binary tree and the value of each node in the heap is greater than or less than its left and right child nodes, it is a heap. According to the value of each node in the heap is greater than or less than its left and right child nodes, it is divided into large root heap and small root heap

Heap sort flow:

  1. Initialize the large (small) root heap, where the root node is the maximum (small) value, and swap the root node with the last node (the last element of the array)
  2. Except for the last node, resize the large (small) root heap so that the root node is the maximum (small) value
  3. Repeat step 2 until there is only one element left in the heap and the sorting is complete

Take [1,5,4,2,3] as an example to build a large root heap:

/ / heap sort
const heapSort = array= > {
        // We store the big root heap in an array, which is the heap itself
	// Initialize the big top heap, starting with the first non-leaf node
	for (let i = Math.floor(array.length / 2 - 1); i >= 0; i--) {
		heapify(array, i, array.length);
	}
	// Sort, each time the for loop finds a current maximum, the array length is reduced by one
	for (let i = Math.floor(array.length - 1); i > 0; i--) {
		// The root node swaps with the last node
		swap(array, 0, i);
		// Start from the root node, and the last node is already the current maximum, so there is no need to participate in the comparison, so the third parameter is I, that is, compare the last node before the last node
		heapify(array, 0, i);
	}
	return array;
};

// Switch two nodes
const swap = (array, i, j) = > {
	let temp = array[i];
	array[i] = array[j];
	array[j] = temp;
};

// Make the heap below I into a big top heap. Note that this step is based on:
// Assume that the subheap below node I is already a big top heap, as implemented by heapify
// Find node I in the heap containing node I.
// We will write a for loop, starting at the first non-leaf node, for each non-leaf node
// All heapify operations are performed, so the subheap below node I is already a big top heap
const heapify = (array, i, length) = > {
	let temp = array[i]; // Current parent node
	// j < length is used to adjust the order of all nodes up to I
	for (let j = 2 * i + 1; j < length; j = 2 * j + 1) {
		temp = array[i]; // Select * from array[I] where array[I] should be
		if (j + 1 < length && array[j] < array[j + 1]) {
			j++; // Find the older of the two children and compare them with the parent node
		}
		if (temp < array[j]) {
			swap(array, i, j); // If the parent node is smaller than the child node, switch; Or jump out
			i = j; // After the swap, the subscript of temp changes to j
		} else {
			break; }}}Copy the code

Resources: IMPLEMENTING heap sort with JS

7. What’s the difference between merge, quicksort and heap

The sorting Time complexity (best case) Time complexity (worst case) Spatial complexity The stability of
Quick sort O(nlogn) O(n^2) O(logn)~O(n) unstable
Merge sort O(nlogn) O(nlogn) O(n) stable
Heap sort O(nlogn) O(nlogn) O(1) unstable

In fact we can see from the table, in terms of time complexity, fast and no big advantage, however why fast row will be the most common methods for sorting, this is because the time complexity indicates that with the increase of the amount of data, algorithm of time trend of price increase does not directly represent the actual execution time, the actual running time also includes a lot of the difference of constant parameters, In addition, in the face of different types of data (such as ordered data, a large number of repeated data), the performance is also different. Generally speaking, the time efficiency of fast sorting is the highest

In practice, not only one sort method is used. For example, V8 array.sort () adopts insert sort when n<=10, and three-way fast sort when n>10


Design patterns

There are many design patterns, but here are a few that are commonly used:

Design patterns describe example
The singleton pattern A class can only construct a unique instance Redux/Vuex的store
The factory pattern Encapsulating the logic for creating objects JQuery’s $(selector)
Observer model When an object is modified, its dependent objects are automatically notified Redux subscribe, Vue bidirectional binding
Decorator mode The wrapping of a class dynamically extends the functionality of the class React Advanced components, ES7 decorators
Adapter mode Compatible with old and new interfaces, packaging of classes Encapsulate the old API
The proxy pattern Controls access to objects Event Proxy, ES6 Proxy

1. Introduce the single responsibility principle and the open and closed principle

  • The single responsibility principle: a class is responsible for the corresponding responsibility in a functional area, or can be defined as: for a class, there should be only one cause for its change.

  • Open Closed Principle: The core idea is that software entities (classes, modules, functions, etc.) are extensible but not modifiable. That is, open for extension and closed for modification.


2. Singleton mode

Singleton mode means that a class can only construct a unique instance. The significance of singleton mode is shared and unique. Store in Redux/Vuex, $in JQ, shopping cart and login box in business scenarios are all applications of singleton mode

class SingletonLogin {
  constructor(name,password){
    this.name = name
    this.password = password
  }
  static getInstance(name,password){
    // Determine whether the object has been created, if so, return the old object
    if(!this.instance)this.instance = new SingletonLogin(name,password)
    return this.instance
  }
}
 
let obj1 = SingletonLogin.getInstance('CXK'.'123')
let obj2 = SingletonLogin.getInstance('CXK'.'321')
 
console.log(obj1===obj2)    // true
console.log(obj1)           // {name:CXK,password:123}
console.log(obj2)           {name:CXK,password:123}
Copy the code


3. Factory mode

The factory pattern is the encapsulation of the logic for creating objects, or simply the encapsulation of new. This encapsulation is like the factory for creating objects, hence the factory pattern. Factory mode is common in large projects, such as JQ’s $object. The reason we create a selector object without a new selector is because $() is already a factory method. Other examples such as react.createElement () and Vue.component() are implementations of factory mode. There are many kinds of factory patterns: simple factory pattern, factory method pattern, and Abstract factory pattern. Here we take the simple factory pattern as an example:

class User {
  constructor(name, auth) {
    this.name = name
    this.auth = auth
  }
}

class UserFactory {
  static createUser(name, auth) {
    // The factory encapsulates the logic for creating objects:
    For admin,auth=1; for user,auth= 2
    // When creating objects, users do not need to know which fields correspond to each permission, and do not need to know the logic of authorization, just need to know that an administrator and a user have been created
    if(auth === 'admin')  new User(name, 1)
    if(auth === 'user')  new User(name, 2)}}const admin = UserFactory.createUser('cxk'.'admin');
const user = UserFactory.createUser('cxk'.'user');
Copy the code


4. Observer mode

The observer pattern is one of the most commonly used design patterns for the front end. The concept of the observer pattern is simple: The observer listens for changes made by the observed, and notifies all observers of changes made by the observed. The observer pattern is widely used in the implementation of listening events, and for more details, see my other article on the Redux implementation

/ / observer
class Observer {    
  constructor (fn) {      
    this.update = fn    
  }
}
// Observed
class Subject {    
    constructor() {        
        this.observers = []          // Observer queue
    }    
    addObserver(observer) {          
        this.observers.push(observer)// Add an observer to the observer queue
    }    
    notify() {                       // Notifies all observers that the observer update() is executed
        this.observers.forEach(observer= > {        
            observer.update()            // Take the observer in turn and execute the observer update method}}})var subject = new Subject()       // Observed
const update = (a)= > {console.log('Notified by the observed')}  // The method to execute when a broadcast is received
var ob1 = new Observer(update)    // Observer 1
var ob2 = new Observer(update)    // Observer 2
subject.addObserver(ob1)          // Observer 1 subscribes to subject notifications
subject.addObserver(ob2)          // Observer 2 subscribes to subject notifications
subject.notify()                  // Issue a broadcast to execute the update method for all observers
Copy the code

Some articles also refer to the observer model as publish-subscribe, but there is a difference. Publish-subscribe has one more dispatch center than the observer model.


5. Decorator mode

The decorator pattern, which can be understood as a wrapper around a class, dynamically extends the functionality of the class. ES7’s decorator syntax and HoC in React are implementations of this pattern. React-redux connect() also uses decorator mode, using ES7 decorators as an example:

function info(target) {
  target.prototype.name = 'Joe'
  target.prototype.age = 10
}

@info
class Man {}

let man = new Man()
man.name / / zhang SAN
Copy the code


6. Adapter mode

The adapter pattern, which converts one interface into another that the customer wants, enables classes with incompatible interfaces to work together. We often use adapters in our life, such as outbound travel plug socket does not match, then we need to use conversion plug, that is, adapter to help us solve the problem.

class Adaptee {
  test() {
      return 'Old interface'}}class Target {
  constructor() {
      this.adaptee = new Adaptee()
  }
  test() {
      let info = this.adaptee.test()
      return ` adaptation${info}`}}let target = new Target()
console.log(target.test())
Copy the code


7. Proxy mode

Proxy mode, for an object to find a replacement object, so that the original object can be accessed. That is to add a layer of proxy between the visitor and the target object, through the proxy to do authorization and control. The most common example is the business of a broker acting for a star. Suppose you, as an investor, want to contact a star for advertising, you need to go through a broker first. The broker checks your qualifications, notifies you of the star’s schedule, and filters unnecessary information for the star himself. Event proxy, JQuery $. Proxy, ES6 proxy are all implementations of this mode. The following uses ES6 proxy as an example:

const idol = {
  name: 'CAI X Zheng'.phone: 10086.price: 1000000  / / quotation
}

const agent = new Proxy(idol, {
  get: function(target) {
    // Stop star calls and only provide agent calls
    return 'Broker Tel :10010'
  },
  set: function(target, key, value) {
    if(key === 'price' ) {
      // Broker filter qualification
      if(value < target.price) throw new Error('The price is too low')
      target.price = value
    }
  }
})


agent.phone        // Broker tel :10010
agent.price = 100  //Uncaught Error: The price is too low
Copy the code


The HTML related

1. Talk about HTML5’s new features in tags, attributes, storage, and apis

  • Tag: Added semantic tag (aside / figure / section / header / footer / navEtc.), add multimedia labelsvideoandaudio, allowing for more separation of style and structure
  • Properties: Enhanced forms, mainly enhancedinputThe Type attribute of themetaAdd charset to set character set.scriptAdded async to load scripts asynchronously
  • Storage: addlocalStorage,sessionStorageandindexedDBAre introduced,application cacheCache the Web and applications
  • API: increaseDrag and drop API,geolocation,SVG drawing,Canvas drawing,Web Worker,WebSocket


2. What is the function of docType?

Declare the document type and tell the browser what document standards to use to parse the document:

  • Weird mode: The browser parses the document using its own mode, which defaults to weird mode when doctype is not added
  • Standard mode: Browsers parse documents using W3C standards


3. Several front-end storage and the differences between them

  • Cookies: The main method of local storage before HTML5, the size is only 4K, HTTP request header will automatically carry cookies, good compatibility
  • LocalStorage: New feature in HTML5, persistent storage, which will not be cleared even if the page is closed, stored as key-value pairs, size 5M
  • SessionStorage: new HTML5 feature, operation and size of the same as localStorage, and localStorage difference is that sessionStorage is cleared when the TAB (page) is closed, and different TAB sessionStorage does not communicate with each other
  • IndexedDB: a NoSQL database, similar to MongoDB, uses key-value pairs to store the database asynchronously, supports transactions, and can store more than 250MB of storage space. However, IndexedDB is restricted by the same origin policy
  • Web SQL: it is a relational database simulated in the browser. Developers can operate Web SQL through SQL statements. It is a set of independent specifications other than HTML5, with poor compatibility


4. What’s the difference between href and SRC

Href (hyperReference) : when the browser encounters href, it downloads resources in parallel without blocking page parsing. For example, when we use to import CSS, the browser downloads CSS in parallel without blocking page parsing. Therefore, we recommend using instead of @import when importing CSS

<link href="style.css" rel="stylesheet" />
Copy the code

SRC (Resource) is a resource. When the browser encounters SRC, it suspends page parsing until the resource has been downloaded or executed, which is why the script tag is placed at the bottom

<script src="script.js"></script>
Copy the code


5. What are the attributes of meta and what are their functions

Meta tags are used to describe meta information, such as website author, description, and keywords. Meta defines information in the form of name= XXX and Content = XXX. Common Settings are as follows:

  • Charset: Defines the character set for an HTML document
 <meta charset="UTF-8" >
Copy the code
  • Http-equiv: Can be used to simulate HTTP request headers, set expiration time, cache, refresh
The < meta - equiv = HTTP"expires" content="Wed, 20 Jun 2019 22:33:00 GMT">Copy the code
  • Viewport: the viewport is used to control the page width, height and zoom ratio
<meta 
    name="viewport" 
    content="width=device-width, initial-scale=1, maximum-scale=1"
>
Copy the code

6. What parameters does viewport have and what are their functions

  • Default width: 980px
  • Initial-scale: indicates the initial scaling ratio, ranging from 1 to 10
  • Maximum-scale /minimum-scale, the maximum /minimum scale that allows the user to scale
  • User-scalable, user scalable (yes/no)

7. Functions and parameters of the http-equive property

  • Expires: Specifies an expiration time
  • Progma: no-cache disables caching
  • Refresh refresh periodically
  • Set-cookie: the cookie can be set
  • X-ua-compatible, using the browser version
  • Apple-mobile-web-app-status-bar-style: Hides the status bar or sets the status bar color for the WebApp full-screen mode


CSS related

Method to clear the float

Why clear float: Clear float is to solve the problem of child element float causing parent element height collapse

1. Add new elements

<div class="parent">
  <div class="child"></div>
  <! Add an empty element using CSS clear:both -->
  <div style="clear: both"></div>
</div>  
Copy the code

2. Use pseudo-elements

/* Add a pseudo-element */ to the parent element
.parent::after{
  content: "";
  display: block;
  height: 0;
  clear:both;
}
Copy the code

3. Trigger the parent element BFC

/* Triggers the parent element BFC */
.parent {
  overflow: hidden;
  /* float: left; * /
  /* position: absolute; * /
  /* display: inline-block */
  /* All of the above attributes can trigger BFC */
}
Copy the code


Introduce the Flex layout

Actually I had also written a section of the horizontal/vertical center related, but feel content based also accounts for too long, so deleted, as a summary of the article, this section should not start from what is “flex”, spindle, lateral axis believe that these concepts used flex layout all know, so we directly with the several properties in the flex:

Container properties (using properties on flex layout containers)

  • Context-content defines the alignment of child elements along the main axis (horizontal axis)
.container {
    justify-content: center | flex-start | flex-end | space-between | space-around;
    / * main shaft alignment: center | left-aligned (default) | right-aligned | full-justified around (a margin between elements are equal) | alignment (each child element margin is equal on both sides) * /
}
Copy the code
  • Align-items defines how items are aligned on the cross axis (vertical axis)
.container {
    align-items: center | flex-start | flex-end | baseline | stretch;
    / * side shaft alignment: under the center alignment at | | | project the first line of the text of the baseline aligned | not set high, if the child elements will fill the whole container height (default) * /
}
Copy the code
  • Flex-direction Direction of the main axis (horizontal axis)
.container {
    flex-direction: row | row-reverse | column | column-reverse;
    / * principal axis direction: horizontal arranged from left to right (default) | | level from right to left vertical top-down vertical bottom-up * / |
}
Copy the code
  • Flex-wrap line wrap
.container {
    flex-wrap: nowrap | wrap | wrap-reverse;
    / * line way: no newline (default) | | return reverse line * /
}
Copy the code
  • Flex-flow The flex-flow property is short for the flex-direction property and flex-wrap
.container {
    flex-flow: <flex-direction> || <flex-wrap>;
    /* Default value: row nowrap */
}
Copy the code
  • Align-content defines the alignment of multiple axes
.container {
    align-content: center | flex-start | flex-end | space-between | space-around | stretch;
    / * default: with the halfway point of the cross shaft alignment with the starting point of cross shaft alignment | | and the end of the cross shaft alignment full-justified | | and cross shaft axis each interval are equal on both sides of the | (default) : the axis with the cross shaft * /
}
Copy the code


Item attributes (attributes used on child elements within the container)

  • Flex-grow defines the project’s zoom scale, which defaults to 0 and does not zoom even if there is free space. If all child elements flex-grow are 1, the remaining space is divided equally, and if one child element flex-grow is 2, that child element takes up twice the remaining space
.item {
  flex-grow: <number>; /* default 0 */
}
Copy the code
  • flex-shrink

    Defines the scaling of the project, which defaults to 1, that is, if there is insufficient space, the child elements will shrink. If all the childrenflex-shrinkThey’re all 1’s, some child elementflex-shrinkIs 0, then the child element will not shrink
.item {
  flex-shrink: <number>; /* default 1 */
}
Copy the code
  • Flex-basis defines the main axis of space that an item occupies before allocating extra space. By default, auto is the original size of the child element, and if set to a fixed value, the child element will occupy a fixed space
.item {
  flex-basis: <length> | auto; /* default auto */
}
Copy the code
  • Flex Flex is a short term for flex-grow, flex-shrink, and flex-basis. The default value is 0. 1 Auto
.item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'>]}Copy the code

Flex has two quick values: auto and None, representing 1, 1 auto (if there is enough space, the equal ratio is reduced, and the child element occupies the same size) and 0, 0 Auto (if there is enough space, the child element occupies the same size)

  • Order defines the order of items. The smaller the value is, the more advanced it is. The default value is 0
.item {
  order: <integer>;
}
Copy the code
  • Align-self defines the arrangement of individual child elements. For example, align-items sets center so that all child elements are centered and aligned. Then you can set the sorting of child elements individually by setting a child element to align-self
.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
Copy the code

Reference: Ruan Yifeng Flex layout


Common layout

Edit, please wait a moment -_ – | |


What is landing

Simply put, A BFC is an isolated and independent container on a page that is not subject to interference or interference from the outside world

How do I trigger the BFC

  • floatDon’t to none
  • overflowIs not visible
  • positionAs absolute or fixed
  • displayIs inline-block or table-cell or table-caption or grid

What are the rendering rules of the BFC

  • A BFC is a separate container on a page that is isolated from outside interference or interference with the outside world
  • When calculating the height of the BFC, floating child elements also participate in the calculation (i.e. height collapse does not occur with floating elements inside).
  • The region of the BFC does not overlap with the element region of float
  • The elements inside the BFC are placed vertically
  • Margins of two adjacent elements in the BFC will overlap

BFC application scenarios

  • Clear float: Float elements inside the BFC participate in height calculations, so they can be used to clear floats and prevent height collapses
  • Avoid an element being overwritten by a floating element: the region of the BFC does not overlap the region of the floating element
  • Prevent margin overlap: Margins of two adjacent boxes belonging to the same BFC will be folded, but not of different BFC


conclusion

For the front end of the basic knowledge of the explanation, here is a short paragraph. The world at the front is far more complex than I can describe in a few words. I am like a child picking up shells on the beach, and sometimes I am so excited by them that I cannot wait to share them with my friends.

Finally want to disgracefully express (since) (boast) about (• ‾ ̑ ⌣ ‾ ̑ •) ✧ ˖ ° : unconsciously, in Denver have water for more than half a year, the six months I write nearly 60000 words, but in fact, a total of only five articles, that’s because I don’t want to write hydrology, don’t want to put the foundation of water dozens to several thousand words mixed upgrade. Write an article, the first to be able to convince yourself. Take responsibility for what you write down, even if it’s a picture or a punctuation mark. The first figure, for example, I adjusted the more than ten times, the first time I intercept Babel transformation result directly and don’t feel good, with a code block, or not good, and replaced by carbon code figure, first download, found that two picture width, filling the width to download, and find your own code without a space, to download, In order to achieve the side-by-side effect of two pictures, I wrote an HTML to adjust the style of the two pictures. In order to ensure the consistency of the content and margin of each picture, I recorded the size and margin of each screenshot while taking a screenshot, and adjusted the margin of each screenshot according to the data of the last one.

In fact, I do not advocate spending time on such details, but I simply think that if the article is not well written, it cannot be published. As Mr. Jiro Ono said, “If the food is not well cooked, it cannot be presented to the guests.” The general truth in the world is often so simple and simple.

Previous articles:

1. Asynchronous programming two or three things | Promise/async/Generator principle parsing words | 9 k 2. 10 lines of code to see all redux implementation – redux & react – redux & redux middleware design to realize the 8 k | 3. Red and black tree red and black fruit, red and black tree introduction to you and me – red and black tree | 6 4 k word. Further React rendering of a service principle | 1 w