66 knowledge points of JavaScript interview

User 4456933 2021-06-18 08:12:49
knowledge points javascript interview


author :Jake Zhang https://juejin.cn/post/6844904200917221389

Preface

I just want to have a face CV The engineer , The interviewer asked me to challenge the rocket engineer , In addition, this year's situation is even worse Two men , But no matter how difficult it is to live on , I still need to keep looking for a job . In the recent interview, I have been summing up , Every time I come back from the interview, I will come back , The following is the interview knowledge I met these days . But today's topic is written in the title 66 strip JavaScript Knowledge point , from the shallower to the deeper , For a week , Every time (zhěng) God (lǐ) whole (bù) The reason is ( yì)10 strip ( qiú) Left (diǎn) Right (zàn), I hope it can be helpful to those who are looking for a job , If there is something wrong in the text , Also please indicate .

HTML&CSS:

  • Browser kernel
  • The box model 、flex Layout 、 two / Three column layout 、 level / Vertical center ;
  • BFC、 Remove the floating ;
  • css3 Animation 、H5 New characteristics .

JavaScript:

  • Inherit 、 Prototype chain 、this Point to 、 Design patterns 、call, apply, bind,;
  • new Realization 、 Anti shake throttling 、let, var, const difference 、 Temporary dead zone 、event、loop;
  • promise Use and implement 、promise Parallel execution and sequential execution ;
  • async/await Advantages and disadvantages ;
  • Closure 、 Garbage collection and memory leaks 、 Array methods 、 Array scrambling , Flattening arrays 、 Event delegation 、 Event monitoring 、 Event model

Vue:

  • vue Principle of data bidirectional binding ;
  • vue computed principle 、computed and watch The difference between ;
  • vue Compiler structure diagram 、 Life cycle 、vue Component communication ;
  • mvvm Pattern 、mvc Mode understanding ;
  • vue dom diff、vuex、vue-router

The Internet :

  • HTTP1, HTTP2, HTTPS、 common http Status code ;
  • Browse what happened from URL entry to carriage return ;
  • Front end security (CSRF、XSS)
  • Front end cross domain 、 Browser cache 、cookie, session, token, localstorage, sessionstorage;
  • TCP Connect ( Three handshakes , Four waves )

Performance related

  • The way pictures are optimized
  • 500 A picture , How to implement preload optimization
  • Lazy loading implementation
  • Reduce http How to request
  • webpack How to configure large projects

In addition, I am also sorting out a more comprehensive set of interview questions , Let's give you a preview :

Let's get to the point :

1. Introduce to you js What are the data types of , How values are stored

See my previous article for details :「 Front end package 」 Probably the most thorough JavaScript Data type details

JavaScript Altogether 8 Type of data , Among them is 7 Basic data types :Undefined、Null、Boolean、Number、String、Symbol(es6 newly added , Represents a unique value ) and BigInt(es10 newly added );

1 Types of reference data ——Object(Object It is essentially composed of a set of unordered name value pairs ). It contains function、Array、Date etc. .JavaScript No mechanism for creating custom types is supported , And all the values will eventually be the above 8 One of the data types .

Raw data type : Directly stored in Stack (stack) in , Small occupation space 、 Fixed size , Belongs to frequently used data , So it's stored in the stack .

Reference data type : At the same time, it is stored in Stack (stack) and Pile up (heap) in , Occupy a large space 、 Size is not fixed . Reference data types store pointers in the stack , The pointer points to the starting address of the entity in the heap . When the interpreter looks for a reference value , Will first retrieve its address in the stack , Get the address and get the entity from the heap .

2. && 、 || and !! What can operators do respectively

  • && It's called logic and , Finds the first virtual expression in its operand and returns it , If no virtual expression is found , Returns the last true expression . It uses a short circuit to prevent unnecessary work .
  • || It's called logic or , Finds the first true expression in its operand and returns it . This also uses a short circuit to prevent unnecessary work . In support of ES6 Before default function arguments , It is used to initialize the default parameter values in the function .
  • !! Operator to cast the value on the right to a Boolean value , This is also a simple way to convert a value to a Boolean value .

3. js The data type conversion of

stay JS There are only three types of conversion in , Namely :

  • Convert to Boolean ( call Boolean() Method )
  • Convert to number ( call Number()、parseInt() and parseFloat() Method )
  • Convert to string ( call .toString() perhaps String() Method )
null and underfined No, .toString Method

There are also some operators that have implicit conversions , No expansion here , Can own Baidu 00

4. JS The judgment of data type in ( typeof,instanceof,constructor,Object.prototype.toString.call()

(1)typeof

typeof For primitive types , except null Can show the right type

console.log(typeof 2); // number
console.log(typeof true); // boolean
console.log(typeof 'str'); // string
console.log(typeof []); // object [] The data type of the array is in typeof Is interpreted as object
console.log(typeof function(){}); // function
console.log(typeof {}); // object
console.log(typeof undefined); // undefined
console.log(typeof null); // object null The data type of is typeof Interpreted as object

typeof For objects , All but functions are displayed object, So typeof We can't judge exactly what kind of variable it is , So I want to judge the correct type of an object , Consider using instanceof

(2)instanceof

instanceof Can correctly judge the type of object , Because the internal mechanism is to determine whether the type can be found in the prototype chain of the object prototype.

console.log(2 instanceof Number); // false
console.log(true instanceof Boolean); // false
console.log('str' instanceof String); // false
console.log([] instanceof Array); // true
console.log(function(){} instanceof Function); // true
console.log({} instanceof Object); // true
// console.log(undefined instanceof Undefined);
// console.log(null instanceof Null);

You can see the direct literal value to judge the data type ,instanceof Can accurately determine the reference data type (Array,Function,Object), And the basic data type cannot be instanceof Accurate judgment .

Let's take a look instanceof stay MDN Explanation in :instanceof Operator is used to test whether an object has a constructor in its prototype chain prototype attribute . It means to judge whether the object is a certain data type ( Such as Array) Example , Focus on whether an object is an instance of a data type . The literal value here is ,2, true ,'str' Not the instance , So the judgment value is false.

(3)constructor

console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true
 There's a pit here , If I create an object , Change its prototype ,constructor It will become unreliable
function Fn(){};
Fn.prototype=new Array();
var f=new Fn();
console.log(f.constructor===Fn); // false
console.log(f.constructor===Array); // true

(4)Object.prototype.toString.call() Use Object Prototype methods of objects toString , Use call Change the crown prince for a civet cat , To borrow Object Of toString Method

var a = Object.prototype.toString;
console.log(a.call(2));
console.log(a.call(true));
console.log(a.call('str'));
console.log(a.call([]));
console.log(a.call(function(){}));
console.log(a.call({}));
console.log(a.call(undefined));
console.log(a.call(null));

5. Introduce js What are the built-in objects ?

js The built-in objects in are mainly those that exist in the global scope before the program is executed js Some global value properties defined by 、 Functions and constructors used to instantiate other objects Number object . In general, we often use global variable values NaN、undefined, Global functions such as parseInt()、parseFloat() The construct used to instantiate an object Make functions, such as Date、Object etc. , There are also single built-in objects that provide mathematical calculations, such as Math object .

Knowledge points involved :

 Global objects ( global objects ) Or standard built-in objects , Do not mix " Global object (global object)" confusion . The global object here is to say in
Objects in global scope . Other objects in the global scope can be created by the user's script or provided by the host program .
Classification of standard built-in objects
(1) Value attribute , These global properties return a simple value , These values have no properties or methods of their own .
for example Infinity、NaN、undefined、null Literal
(2) Function attribute , Global functions can be called directly , There is no need to specify the owning object when calling , After execution, the result is returned directly to the caller .
for example eval()、parseFloat()、parseInt() etc.
(3) The basic object , Basic objects are the basis for defining or using other objects . Basic objects include general objects 、 Function objects and error objects .
for example Object、Function、Boolean、Symbol、Error etc.
(4) Number and date objects , Used to represent numbers 、 Dates and objects that perform mathematical calculations .
for example Number、Math、Date
(5) character string , Object used to represent and manipulate strings .
for example String、RegExp
(6) Indexable collection objects , These objects represent a collection of data sorted by index values , Including arrays and type arrays , And objects of class array structure . for example Array
(7) Collection objects using keys , These collection objects use keys when storing data , Supports iteration of elements in insertion order .
for example Map、Set、WeakMap、WeakSet
(8) Vector set ,SIMD The data in a vector set is organized into a data sequence .
for example SIMD etc.
(9) Structured data , These objects are used to represent and manipulate structured buffer data , Or use JSON Encoded data .
for example JSON etc.
(10) Control abstract objects
for example Promise、Generator etc.
(11) Reflection
for example Reflect、Proxy
(12) internationalization , To support multilingual processing ECMAScript The object of .
for example Intl、Intl.Collator etc.
(13)WebAssembly
(14) other
for example arguments

For details, please refer to :《 Classification of standard built-in objects 》

《JS Summary of all built-in object properties and methods 》

6. undefined And undeclared The difference between ?

Variables that have been declared in the scope but not yet assigned , yes undefined. contrary , Variables not yet declared in scope , yes undeclared Of .

about undeclared References to variables , The browser will report a reference error , Such as ReferenceError: b is not defined . But we can use typ eof To avoid error reporting , Because for undeclared( perhaps not defined ) Variable ,typeof Returns the "undefined".

7. null and undefined The difference between ?

First Undefined and Null It's all basic data types , Each of these two basic data types has only one value , Namely undefined and null.

undefined The meaning of representation is undefined , null It means empty object ( It's not a real object , Please look at the following Be careful !). When a general variable is declared but not defined, it will return undefined,null It is mainly used to assign values to variables that may return objects , As initialization .

 Actually null Not object , although typeof null Will be output object, But it's just JS There is a long history Bug. stay JS In the original version of 32 Bit system , For performance reasons, use low-level storage variables for type information ,000 The beginning represents the object , However null It's all zero , So it's wrong to say object . Although the current internal type determination code has changed , But for this Bug But it has been handed down all the time .

undefined stay js Chinese is not a reserved word , This means that we can use undefined As a variable name , This is very dangerous , it It will affect our response to undefined Value judgment . But there are some ways we can get secure undefined value , for instance void 0.

When we use typeof When judging ,Null Typing returns “object”, This is a problem left over by history . When we use double equal When comparing two types of values, it returns true, Using three equal signs returns false.

For details, please refer to :

《JavaScript In depth understanding of undefined And null》

8. {} and [] Of valueOf and toString What is the result ?

{} Of valueOf The result is {} ,toString As the result of the "[object Object]"
[] Of valueOf The result is [] ,toString As the result of the ""

9. Javascript Scope and scope chain of

Scope : Scope is the area where variables are defined , It has a set of rules for accessing variables , This set of rules govern how the browser engine depends on variables in the current scope as well as nested scopes ( identifier ) Find variables .

Scope chain : The role of scope chain is to ensure orderly access to all variables and functions that have access to the execution environment , Through the scope chain , We can access variables in the outer environment and function .

A scope chain is essentially a list of pointers to a variable object . A variable object is an object that contains all variables and functions in the execution environment . Before the scope chain The end is always the variable object of the current execution context . Global execution context variable object ( That is, global objects ) Always the last object in the scope chain .

When we look for a variable , If not found in the current execution environment , We can look backward along the scope chain .

The creation process of scope chain is related to the establishment of execution context ....

For details, please refer to :《JavaScript In depth understanding of the scope chain 》

You can also look at my article :「 Front end package 」 Go deep into JavaScript Scope ( chain ) Knowledge points and closures

10. javascript Several ways to create objects ?

We usually create objects directly in the form of literals , But this kind of creation method is suitable for creating a large number of similar objects , There's a lot of repetitive code . but js Different from general object-oriented languages , stay ES6 It didn't have the concept of a class before . But we can use functions to simulate , Thus, reusable objects are produced How it was created , There are several ways I've learned :

(1) The first is the factory model , The main working principle of factory mode is to use functions to encapsulate the details of creating objects , In order to achieve the purpose of reuse by calling functions . But it has a big problem that the created objects can't be associated with a certain type , It simply encapsulates the reuse code , Instead of establishing a relationship between objects and types .

(2) The second is the constructor pattern .js Each function in can be used as a constructor , As long as a function is passed through new To invoke the , So we can call it a constructor . Executing a constructor first creates an object , Then point the prototype of the object to the constructor prototype attribute , Then it will execute this Point to this object , Finally, the entire function is executed , If the return value is not an object , The new object is returned . because this The value of points to the newly created object , So we can use this Assign a value to an object . The advantage of the constructor pattern over the factory pattern is , The object created is linked to the constructor , So we can use prototypes to identify the types of objects . But one drawback of constructors is that , Create an object that is unnecessary , Because in js The middle function is also an object , So if an object property contains a function , So every time we create a new function object , Wasted unnecessary memory space , Because functions are universal to all instances .

(3) The third pattern is the prototype pattern , Because every function has a prototype attribute , This property is an object , It contains properties and methods that can be shared by all instances created through constructors . So we can use prototype objects to add common properties and methods , To achieve code reuse . This approach is relative to the constructor pattern , The reuse of function objects is solved . But there are also some problems with this model , One is that there is no way to initialize values by passing in parameters , The other is if there is a reference type such as Array So the value of the , Then all instances will share an object , A change in the value of a reference type affects all instances .

(4) The fourth pattern is a combination of constructor pattern and prototype pattern , This is the most common way to create custom types . Because there are some problems in using constructor pattern and prototype pattern separately , So we can combine these two patterns , Initializing the properties of an object through a constructor , The reuse of function method is realized by prototype object . This method solves the shortcomings of the two modes when they are used alone , But there's one thing that's not enough , Because two different patterns are used , So the encapsulation of the code is not good enough .

(5) The fifth pattern is the dynamic prototype pattern , This pattern moves the creation of the prototype method assignment to the inside of the constructor , By judging whether an attribute exists , You can implement the effect of assigning a prototype object only once when the function is called for the first time . This is a good way to encapsulate the above mixed mode .

(6) The sixth pattern is the parasitic constructor pattern , The implementation of this mode is basically the same as the factory mode , My understanding of this pattern is , It's mainly based on an existing type , Extend the instantiated object when instantiating . In this way, you don't have to modify the original constructor , It also achieves the purpose of extending objects . One of its drawbacks is the same as the factory model , Unable to implement object recognition .

Well, what I've learned so far is that .

For details, please refer to :《JavaScript Deep understanding of object creation 》

11. JavaScript Several ways to implement inheritance ?

I know js There are several ways to implement inheritance in :

(1) The first is to implement inheritance in the form of prototype chain , But the disadvantage of this implementation is , When you include data of reference type , Will be shared by all instance objects , It is easy to cause confusion in revision . Also, you can't pass parameters to a supertype when you create a subtype .

(2) The second way is to use the borrowing constructor , This is achieved by calling super type constructors in subtype functions , This method solves the problem of not passing parameters to a supertype , But it has a problem that it can't realize the reuse of function method , And the method subtype defined by the supertype prototype has no access to .

(3) The third way is combinatorial inheritance , Composite inheritance is a way to combine prototype chains and borrowing constructors . By borrowing the constructor to implement the inheritance of type properties , Methods are inherited by setting the prototype of a subtype to an instance of a supertype . This method solves the problem of using the above two modes separately , But because we are prototyped with instances of supertypes , So I called the constructor of the superclass twice , This creates a lot of unnecessary properties in the prototype of the subtype .

(4) The fourth way is archetypal inheritance , The main idea of prototype inheritance is to create new objects based on existing objects , The principle of implementation is , Pass an object into the function , It then returns an object prototype of this object . The idea of inheritance is not to create a new type , It's just a simple inheritance of an object ,ES5 As defined in Object.create() Methods are the implementation of prototype inheritance . The disadvantages are the same as the prototype chain .

(5) The fifth way is parasitic inheritance , The idea of parasitic inheritance is to create a function that encapsulates the inheritance process , By passing in an object , And then make a copy of the object , Then the object is extended , Finally, return this object . This extension process can be understood as a kind of inheritance . The advantage of this kind of inheritance is to implement inheritance on a simple object , If the object is not our custom type . The disadvantage is that there is no way to reuse functions .

(6) The sixth way is parasitic combinatorial inheritance , The disadvantage of composite inheritance is that it uses instances of supertypes as prototypes of subtypes , This leads to the addition of unnecessary prototype properties . The way to parasitically combine inheritance is to use a copy of the prototype of a supertype as the prototype of a subtype , This avoids creating unnecessary properties .

For details, please refer to :《JavaScript The inheritance of deep understanding 》

12. Implementation of parasitic composition inheritance ?

{
this.name = name;
}
Person.prototype.sayName = function() {
console.log("My name is " + this.name + ".");
};
function Student(name, grade) {
Person.call(this, name);
this.grade = grade;
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.sayMyGrade = function() {
console.log("My grade is " + this.grade + ".");
};

13. Talk to you about this、call、apply and bind The understanding of the

See my previous article for details :「 Front end package 」 Get a thorough understanding of JavaScript Medium this、call、apply and bind

  1. In the browser , On a global scale this Point to window object ;
  2. In the function ,this Always point to the object that was invoked last ;
  3. In the constructor ,this Point to new The new object that came out ;
  4. call、apply、bind Medium this Is strongly bound to the specified object ;
  5. In the arrow function this A special , Arrow function this Of the parent scope this, Not when called this. You know the first four ways , It is determined when calling , It's dynamic , And the arrow function this The point is static , It was confirmed when the statement was made ;
  6. apply、call、bind All are js Some built-in functions API, Call them to specify this Implementation , At the same time, you can pass on the reference .

14. JavaScript Prototype , Prototype chain ? What are the characteristics of ?

stay js We use the constructor to create a new object , Inside each constructor there is a prototype Property value , This property value is a pair of like , This object contains properties and methods that can be shared by all instances of the constructor . When we create an object with a constructor , Inside the object Will contain a pointer , This pointer points to the constructor prototype The value of the property , stay ES5 This pointer in is called the prototype of the object . Generally speaking, we You should not be able to get this value , But now it's all implemented in browsers proto Property to let us access this property , But we'd better not use this Attributes , Because it's not specified in the specification .ES5 There's a new Object.getPrototypeOf() Method , We can use this method to get the information about The archetype of the elephant .

When we access the properties of an object , If this property does not exist inside this object , Then it will look for this property in its prototype object , This prototype object is again It will have its own prototype , So I kept looking for it , That's the concept of the prototype chain . The end of the prototype chain is usually Object.prototype So this is It's why our new object can be used toString() And so on .

characteristic :

JavaScript Objects are passed by reference , None of the new object entities we create has its own prototype copy . When we modify the prototype , And Its related objects will also inherit this change .

Reference article :

《JavaScript Deep understanding of prototype and prototype chain 》

You can also see what I wrote :「 Front end package 」 In depth understanding of JavaScript Prototypes and prototype chains

15. js How to get the prototype ?

  • p.proto
  • p.constructor.prototype
  • Object.getPrototypeOf(p)

16. What is a closure , Why use it ?

A closure is a function that has access to a variable in the scope of another function , The most common way to create a closure is to create another function within one function , The function created can be Access to the local variable of the current function .

Closures have two common uses .

  • The first use of closures is to make it possible for us to access variables inside functions outside of functions . By using closures , We can call closure functions from outside , To access the variables inside the function from the outside , You can use this method to create private variables .
  • Another purpose of the function is to keep the variable object in the context of the function that has finished running in memory , Because the closure function retains the reference to the variable object , So the variable object is not recycled .
function a(){
var n = 0;
function add(){
n++;
console.log(n);
}
return add;
}
var a1 = a(); // Be careful , The function name is just an identifier ( Pointer to function ), and () It's the executive function ;
a1(); //1
a1(); //2 Second call n Variables are still in memory

In fact, the essence of closure is a special application of scope chain , As long as you understand the creation process of the scope chain , You can understand the implementation principle of closures .

17. What is? DOM and BOM?

DOM The object of a document is a model , It refers to treating a document as an object , This object mainly defines the methods and interfaces for handling web page content .

BOM Refers to the browser object model , It refers to treating the browser as an object , This object mainly defines the method and interface to interact with browser .BOM The core is window, and window Objects have dual roles , It is both through js An interface for accessing browser windows , Another Global( overall situation ) object . This means any object defined in the web page , Variables and functions , All exist as an attribute or method of the global object .window Objects contain locati on object 、navigator object 、screen Object and other sub objects , also DOM The most fundamental object of document Object is also BOM Of window Yes Children of the elephant .

Related information :

《DOM, DOCUMENT, BOM, WINDOW What's the difference? ?》

《Window object 》

《DOM And BOM What are the differences , What's the connection ?》

《JavaScript Learning summary ( 3、 ... and )BOM and DOM Detailed explanation 》

18. What are the three event models ?

event It's the interaction that happens when the user operates the web page or some operation of the web page itself , There are three event models in modern browsers .

  1. DOM0 Level model : , This model doesn't propagate , So there is no concept of event flow , But some browsers now support bubbling , It can directly define the listening function in the web page , It can also be done through js Property to specify the listener function . This approach is compatible with all browsers .
  2. IE Event model : In this event model , There are two processes in an event , Event handling stage , And the bubble stage of events . The event processing phase will first execute the listening event bound by the target element . Then there's the bubble stage of events , Bubbling refers to the event bubbling from the target element to document, Check in turn whether the nodes passing by are bound with event listeners , If so, execute . This model is based on attachEvent To add a listener function , You can add multiple listener functions , Will be executed in sequence .
  3. DOM2 Level event model : In this event model , There are three processes in an event , The first process is the event capture phase . Capture refers to the event from document All the way down to the target element , Check in turn whether the nodes passing by are bound with event listeners , If so, execute . The last two stages and IE The two phases of the event model are the same . This event model , The function of event binding is addEventListener, The third parameter specifies whether the event is executed in the capture phase .

Related information :

《 One DOM Element binding multiple events , Bubble or capture first 》

19. What is the event delegate ?

Event delegation In essence, it takes advantage of the browser event bubble mechanism . Because the event will be uploaded to the parent node during the bubbling process , And the parent node can get through the event object The target node , Therefore, we can define the listening function of the child node on the parent node , The listener function of the parent node uniformly handles the events of multiple child elements , This approach is called event broker .

With the event broker, we don't have to bind a listening event for each child element , This reduces memory consumption . And using event proxy, we can also implement dynamic binding of events , For example, a new child node is added , We don't need to add a listening event to it alone , The events it takes place will be handled by the listener in the parent element .

Related information :

《JavaScript Detailed explanation of the event entrustment 》

20. What is event communication ?

When event It happened in DOM Time on element , The event does not happen entirely on that element . stay “ When an event occurs DOM Time on element , The event does not happen entirely on that element .

There are three stages of event communication :

  1. Capture phase – Events from window Start , Then down to each element , Until the target element event or event.target.
  2. Target stage – Event reached target element .
  3. bubbling phase – Event bubbles from target element , Then go up to each element , Until arrival window.

21. What is event capture ?

When an event occurs DOM Time on element , The event does not happen entirely on that element . In the capture phase , Events from window Start , Up to the element that triggered the event .window----> document----> html----> body \----> Target element

Suppose that HTML structure :

<div class="grandparent">
<div class="parent">
<div class="child">1</div>
</div>
</div>

Corresponding JS Code :

function addEvent(el, event, callback, isCapture = false) {
if (!el || !event || !callback || typeof callback !== 'function') return;
if (typeof el === 'string') {
el = document.querySelector(el);
};
el.addEventListener(event, callback, isCapture);
}
addEvent(document, 'DOMContentLoaded', () => {
const child = document.querySelector('.child');
const parent = document.querySelector('.parent');
const grandparent = document.querySelector('.grandparent');
addEvent(child, 'click', function (e) {
console.log('child');
});
addEvent(parent, 'click', function (e) {
console.log('parent');
});
addEvent(grandparent, 'click', function (e) {
console.log('grandparent');
});
addEvent(document, 'click', function (e) {
console.log('document');
});
addEvent('html', 'click', function (e) {
console.log('html');
})
addEvent(window, 'click', function (e) {
console.log('window');
})
});

addEventListener Method has a third optional parameter useCapture, The default value is false, The event will occur during the bubbling phase , If true, The event will occur in the capture phase . If you click child Elements , It will print separately on the console window,document,html,grandparent and parent, This is it. Event capture .

22. What is event bubbling ?

Event bubbling is the opposite of event capture , The current element ---->body \----> html---->document \---->window. When an event occurs DOM Time on element , The event does not happen entirely on that element . In bubbling stage , Event Bubbling , Or it happens to its parents , My grandparents , Grandparents' parents , Until arrival window until .

Suppose that HTML structure :

<div class="grandparent">
<div class="parent">
<div class="child">1</div>
</div>
</div>

Corresponding JS Code :

function addEvent(el, event, callback, isCapture = false) {
if (!el || !event || !callback || typeof callback !== 'function') return;
if (typeof el === 'string') {
el = document.querySelector(el);
};
el.addEventListener(event, callback, isCapture);
}
addEvent(document, 'DOMContentLoaded', () => {
const child = document.querySelector('.child');
const parent = document.querySelector('.parent');
const grandparent = document.querySelector('.grandparent');
addEvent(child, 'click', function (e) {
console.log('child');
});
addEvent(parent, 'click', function (e) {
console.log('parent');
});
addEvent(grandparent, 'click', function (e) {
console.log('grandparent');
});
addEvent(document, 'click', function (e) {
console.log('document');
});
addEvent('html', 'click', function (e) {
console.log('html');
})
addEvent(window, 'click', function (e) {
console.log('window');
})
});

addEventListener Method has a third optional parameter useCapture, The default value is false, The event will occur during the bubbling phase , If true, The event will occur in the capture phase . If you click child Elements , It will print separately on the console child,parent,grandparent,html,document and window, This is it. Event Bubbling .

23. DOM operation —— How to add 、 remove 、 Move 、 Copy 、 Create and find nodes ?

(1) Create a new node

 createDocumentFragment()
createElement() // Create a specific element
createTextNode() // Create a text node

(2) add to 、 remove 、 Replace 、 Insert

appendChild(node)
removeChild(node)
replaceChild(,old)
insertBefore(new,old)

(3) lookup

getElementById();
getElementsByName();
getElementsByTagName();
getElementsByClassName();
querySelector();
querySelectorAll();

(4) Attribute operation

getAttribute(key);
setAttribute(key, value);
hasAttribute(key);
removeAttribute(key);

Related information :

《DOM summary 》

《 Native JavaScript Of DOM Operation summary 》

《 Native JS in DOM Node related API Collection 》

24. js What are the native methods for arrays and strings , Give me a list

25. Common regular expressions ( Just collecting , It doesn't involve much )

//(1) matching 16 Base color value
var color = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g;
//(2) Match date , Such as yyyy-mm-dd Format
var date = /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/;
//(3) matching qq Number
var qq = /^[1-9][0-9]{4,10}$/g;
//(4) Cell phone number regular
var phone = /^1[34578]\d{9}$/g;
//(5) User name regular
var username = /^[a-zA-Z\$][a-zA-Z0-9_\$]{4,16}$/;
//(6)Email Regular
var email = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
//(7) ID number (18 position ) Regular
var cP = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
//(8)URL Regular
var urlP= /^((https?|ftp|file):\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/;
// (9)ipv4 Address regular
var ipP = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
// (10)// The license plate number is regular
var cPattern = /^[ Beijing, Tianjin, Shanghai, Chongqing, Hebei, Henan, Yunnan, Liaoning, Heilongjiang, Hunan, Anhui, Shandong, new Jiangsu, Zhejiang, Jiangxi, Hubei, Guangxi, Gansu, Shanxi, Inner Mongolia, Shaanxi, Jilin, Fujian, Guizhou, Guangdong, Qinghai Tibet, Sichuan, Ningxia and Hainan A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9 Hang the school police in Hong Kong and Macao ]{1}$/;
// (11) Strong password ( Must contain a combination of upper and lower case letters and numbers , Special characters cannot be used , The length is in 8-10 Between ):var pwd = /^(?=.\d)(?=.[a-z])(?=.[A-Z]).{8,10}$/

26. Ajax What is it? ? How to create a Ajax?

I am right. ajax The understanding is , It's a way of asynchronous communication , By directly by js Script to server http signal communication , And then according to the data returned by the server , Update the corresponding part of the page , Instead of refreshing the entire page .

Creating steps :

Interview handwriting ( Native ):

//1: establish Ajax object
var xhr = window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');// compatible IE6 Up to
//2: To configure Ajax Request address
xhr.open('get','index.xml',true);
//3: Send a request
xhr.send(null); // Rigorous writing
//4: Monitor requests , Accept response
xhr.onreadysatechange=function(){
if(xhr.readySate==4&&xhr.status==200 || xhr.status==304 )
console.log(xhr.responsetXML)
}

jQuery How to write it

 $.ajax({
type:'post',
url:'',
async:ture,//async asynchronous sync Sync
data:data,// in the light of post request
dataType:'jsonp',
success:function (msg) {
},
error:function (error) {
}
})

promise Encapsulation implementation :

// promise Encapsulation implementation :
function getJSON(url) {
// Create a promise object
let promise = new Promise(function(resolve, reject) {
let xhr = new XMLHttpRequest();
// Create a new one http request
xhr.open("GET", url, true);
// Set state listener function
xhr.onreadystatechange = function() {
if (this.readyState !== 4) return;
// When a request succeeds or fails , change promise The state of
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
// Set error listener function
xhr.onerror = function() {
reject(new Error(this.statusText));
};
// Set the data type of the response
xhr.responseType = "json";
// Set the request header information
xhr.setRequestHeader("Accept", "application/json");
// send out http request
xhr.send(null);
});
return promise;
}

27. js How to delay loading ?

js Loading 、 Parsing and execution can block the rendering process of the page , So we hope js Scripts can delay loading as much as possible , Improve the rendering speed of the page .

Several ways I've learned are :

  1. take js The script is at the bottom of the document , To make js The script is loaded and executed at the end as much as possible .
  2. to js Script add defer attribute , This property allows the script to load and parse the document synchronously , Then execute the script file after parsing the document , In this way, the rendering of the page will not be blocked . Multiple settings defer The script for the property is executed in sequence at the end of the specification , But it may not be the case in some browsers .
  3. to js Script add async attribute , This property causes the script to load asynchronously , Does not block the parsing process of the page , But immediately after the script is loaded js Script , At this time, if the document is not parsed, it will also block . Multiple async The execution order of the script for the property is unpredictable , Generally, it is not executed in the order of the code .
  4. Dynamically create DOM How to label , We can monitor the loading events of documents , When the document is loaded, it will be created dynamically script Tag to introduce js Script .

Related information :

《JS Several ways to delay loading 》

《HTML 5 <script> async attribute 》

28. Talk about your understanding of modular development ?

My understanding of modules is , A module is a set of methods to implement a specific function . In the beginning ,js It only implements some simple functions , So there's no concept of modules , But as the program gets more complex , Modular development of code is becoming more and more important .

Because of its independent scope , The most primitive way to write it is to use functions as modules , Several functions as a module , However, it is easy to pollute global variables in this way dye , And there is no connection between modules .

After that, the object writing method is put forward , By using a function as an object , This solves some shortcomings of using functions as modules directly , But this approach will expose There are all the module members , External code can modify the values of internal properties .

Now the most commonly used method is to execute functions immediately , The private scope of module is established by using closure , At the same time, it will not pollute the global scope .

Related information :《 On Modular Development 》

《Javascript Modular programming ( One ): Module writing 》

《 Front-end modularization :CommonJS,AMD,CMD,ES6》

《Module The grammar of 》

29. js Several module specifications for ?

js Now, there are four kinds of module loading schemes :

  • The first is CommonJS programme , It passes through require To introduce modules , adopt module.exports Define the output interface of the module . This module loading scheme is a server-side solution , It introduces modules in a synchronous way , Because on the server side, the files are stored on the local disk , So reading is very fast , So there's no problem loading synchronously . But if it's on the browser side , Because the module is loaded using network requests , So it's more appropriate to use asynchronous loading .
  • The second is AMD programme , This scheme uses asynchronous loading to load modules , The loading of the module does not affect the execution of the following statements , All statements that depend on this module are defined in a callback function , Wait until the load is complete before executing the callback function .require.js Realized AMD standard .
  • The third is CMD programme , This program and AMD The solution is to solve the problem of asynchronous module loading ,sea.js Realized CMD standard . It and require.js The difference is that the processing of dependency is different when module is defined and when it is executed .
  • The fourth option is ES6 The proposal , Use import and export To import and export modules in the form of .

30. AMD and CMD The difference between norms ?

There are two main differences between them .

  1. The first aspect is that dependencies are handled differently when modules are defined .AMD Respect dependence before , When you define a module, you must declare the modules it depends on . and CMD Respect the proximity of dependence , Only when you use a module require.
  2. The second aspect is that the execution timing of dependent modules is different . First AMD and CMD The loading mode of modules is asynchronous loading , But the difference between them is

The timing of module execution ,AMD After the dependent module is loaded, the dependent module is executed directly , The execution order of dependent modules is not necessarily the same as the order we write . and CMD Do not execute after the dependent module is loaded , It's just a download , Wait until all the dependent modules are loaded , Enter callback function logic , encounter require sentence Only when the corresponding module is executed , In this way, the execution order of modules is consistent with the order in which we write .

define(function(require, exports, module) {
var a = require("./a");
a.doSomething();
// Omitted here 100 That's ok
var b = require("./b"); // Dependence can be written nearby
b.doSomething();
// ...
});
// AMD Default recommendation
define(["./a", "./b"], function(a, b) {
// Dependencies must be written at the beginning
a.doSomething();
// Omitted here 100 That's ok
b.doSomething();
// ...
});

Related information :

《 Front-end modularization ,AMD And CMD The difference between 》

31. ES6 Module and CommonJS modular 、AMD、CMD The difference of .

  • 1.CommonJS The output of the module is a copy of the value ,ES6 The module outputs a reference to a value .CommonJS The output of the module is of value

, in other words , Once a value is output , Changes within the module do not affect this value .ES6 The operation mechanism of the module and CommonJS Dissimilarity .JS When the engine statically analyzes the script , Module load command encountered import, It will generate a read-only reference . Wait until the script actually executes , According to this read-only reference , Go to the loaded module to get the value .

  • 2.CommonJS Modules are run time loaded ,ES6 Module is a compile time output interface .CommonJS Modules are objects , That is to load the whole module before input , Generate an object , Then read the method from the object , This load is called “ Load at run time ”. and ES6 Module is not an object , Its external interface is just a static definition , It will be generated during the static parsing phase of the code .

32. requireJS What is the core principle of ?

require.js The core principle of is to create... Dynamically script Scripts to introduce modules asynchronously , And then for each script load Event monitoring , If every script is loaded , Call the callback function again .```

For details, please refer to :《requireJS Analysis of the usage and principle of 》

《requireJS What is the core principle of ?》

《requireJS Principle analysis 》

33. Talk about JS Operation mechanism of

1. js Single thread

JavaScript One of the characteristics of language is single thread , That is, only one thing can be done at a time .

“JavaScript The single thread , Related to its use . As a browser scripting language ,JavaScript Its main purpose is to interact with users , And operation DOM. This determines that it can only be a single thread , Otherwise, it will bring complicated synchronization problems . such as , Assume JavaScript There are two threads at the same time , A thread in a DOM Add content on node , Another thread deleted this node , Which thread should the browser follow ?

therefore , To avoid complexity , From the birth ,JavaScript It's a single thread , This has become the core feature of the language , It won't change in the future .

2. js The event loop

js There are many tasks during code execution , These tasks are divided into two categories :

  • Synchronization task
  • Asynchronous task

When we open the website , The rendering process of a web page is a lot of synchronization tasks , For example, rendering of page skeleton and page elements . And tasks like loading pictures and music take up a lot of resources , It's asynchronous tasks ., We use a map to illustrate :

Let's explain this picture :

  • Synchronous and asynchronous tasks are executed differently " place ", Enter the main thread synchronously , Enter asynchronously Event Table And register functions .
  • When the appointed thing is done ,Event Table Will move this function into Event Queue.
  • The task in the main thread is empty after execution , Will go to Event Queue Read the corresponding function , Enter the main thread execution .
  • The above process will be repeated , That's what they say Event Loop( The event loop ).

When is the main thread execution stack empty ?js The engine exists monitoring process process , It will continuously check whether the main thread execution stack is empty , Once it's empty , Will go Event Queue There's a check to see if there's a function waiting to be called .

That's all js The overall process of operation

Note that in addition to synchronous and asynchronous tasks , Tasks can be further subdivided into macrotask( Macro task ) and microtask( Micro task ),js The engine will give priority to micro tasks

 Micro tasks include promise The callback 、node Medium process.nextTick 、 Yes Dom Change the monitoring of MutationObserver.
Macro tasks include script Script execution 、setTimeout ,setInterval ,setImmediate A class of timed events , What's more I/O operation 、UI Shading
Dye, etc .

How to answer in the interview ? The following is my personal recommendation :

  1. First js It's single threaded , When the code is executed , By pushing the execution context of different functions into the execution stack to ensure the orderly execution of the code .
  2. When executing synchronization code , If an asynchronous event is encountered ,js The engine doesn't always wait for its results to return , It will suspend the event , Continue to perform other tasks in the execution stack
  3. When the synchronization event is executed , Then add the callback corresponding to the asynchronous event to another task queue different from the current execution stack to wait for execution .
  4. Task queue can be divided into macro task column and micro task pair column , When the event in the current execution stack has been executed ,js The engine first determines whether there are tasks in the microtask pair column that can be executed , If there is, the event of the head of the micro task team will be pushed into the stack for execution .
  5. When the task in the column has been executed by the micro task, the macro task can be judged to the task in the column .

Finally, we can test the harvest with the following question :

setTimeout(function() {
console.log(1)
}, 0);
new Promise(function(resolve, reject) {
console.log(2);
resolve()
}).then(function() {
console.log(3)
});
process.nextTick(function () {
console.log(4)
})
console.log(5)

The first round : The main thread starts executing , encounter setTimeout, take setTimeout The callback function of the macro task queue , It's going down new Promise Execute now , Output 2,then The callback function is dropped to the micro task queue , And go on with it , encounter process.nextTick, Also throw the callback function to the task queue , And go on with it , Output 5, When all synchronization tasks are completed, check whether there are micro tasks that can be executed , Found to have then Functions and nextTick Two micro tasks , Which one to execute first ?process.nextTick The specified asynchronous task always occurs before all asynchronous tasks , So first execute process.nextTick Output 4 And then execute then Output function 3, The first round of execution ended . The second round : Start with the macro task queue , Find out setTimeout Callback , Output 1 completion of enforcement , So the result is 25431

Related information :

《 Browser event loop mechanism (event loop)》

《 Detailed explanation JavaScript Medium Event Loop( The event loop ) Mechanism 》

《 What is? Event Loop?》

《 This time, , Understand thoroughly JavaScript Execution mechanism 》

34. arguments What is the object of ?

arguments Object is a collection of parameter values passed in a function . It's an array like object , Because it has a length attribute , We can use array index notation arguments[1] To access individual values , But it has no built-in methods in the array , Such as :forEach、reduce、filter and map.

We can use Array.prototype.slice take arguments Object to an array .

{
return Array.prototype.slice.call(arguments);
}

Be careful : Not in arrow function arguments object .

{
return arguments;
}
const two = function () {
return arguments;
}
const three = function three() {
return arguments;
}
const four = () => arguments;
four(); // Throws an error - arguments is not defined

When we call a function four when , It throws out one ReferenceError: arguments is not defined error. Use rest grammar , Can solve this problem .

 four = (...args) => args;

This will automatically put all parameter values into the array .

35. Why is this function called , In code b It becomes a global variable ?

{
let a = b = 0;
}
myFunc();

The reason is that assignment operators are evaluated from right to left . This means that when multiple assignment operators appear in an expression , They are evaluated from right to left . So that's what the code above looks like :

{
let a = (b = 0);
}
myFunc();

First , expression b = 0 evaluation , In this case b No statement . therefore ,JS The engine creates a global variable outside of this function b, Expression after b = 0 The return value of is 0, And assign new local variables a.

We can solve this problem by declaring variables before assigning values .

{
let a,b;
a = b = 0;
}
myFunc();

36. A brief introduction V8 The garbage collection mechanism of the engine

v8 The garbage collection mechanism of is based on generational collection mechanism , This mechanism is based on the generational hypothesis , This hypothesis has two characteristics , First, the new object is easy to die early , The other is that the immortal will live longer . Based on this hypothesis ,v8 The engine divides memory into new and old generations .
Newly created objects or objects that have experienced only one garbage collection are called the new generation . Objects that have been garbage collected many times are referred to as the "old generation" .
The new generation is divided into From and To Two spaces ,To It's usually idle . When From When the space is full Scavenge Algorithm for garbage collection . When we execute the garbage collection algorithm, the application logic will stop , Wait until the garbage collection is over . This algorithm is divided into three steps :
(1) First check From The living object of space , If the object survives, it is judged whether the object meets the conditions for promotion to the old generation , If you meet the requirements, you will be promoted to the older generation . If not, move To Space .
(2) If the object doesn't survive , Then release the space of the object .
(3) The final will be From Space and To Space roles are exchanged .
There are two conditions for the new generation to be promoted to the old generation :
(1) The first is to judge whether the object has been passed once Scavenge Recycling . If you have experienced , Then the object is changed from From Space is copied into the old generation ; If you don't experience , Copy to To Space .
(2) The second is To Whether the memory usage ratio of space exceeds the limit . When the object from From Space copied to To When space , if To Space use exceeds 25%, Then the object is promoted directly to the old generation . Set up 25% The main reason is that after the algorithm is finished , When the two spaces are finished, they will switch positions , If To Space memory is too small , Will affect subsequent memory allocation .
In the old generation, mark clearing method and label compression method were used . Mark clearing first marks the surviving objects in memory , After marking, clear the unmarked objects . Because the mark will cause a lot of memory fragmentation after clearing , It's not easy to allocate memory later . Therefore, to solve the problem of memory fragmentation, the label compression method is introduced .
Because the logic of the application will be suspended during garbage collection , For the new generation method, due to the small memory , Each pause will not be too long , But for the older generation, each garbage collection takes a long time , A pause can have a big impact . To solve this problem V8 The incremental marking method is introduced , Divide a pause into multiple steps , Each time a small step is completed, let the running logic execute for a while , So it's running alternately .

Related information :

《 In depth understanding of V8 The principle of garbage collection 》

《JavaScript Garbage collection in 》

37. What operations can cause memory leaks ?

  • 1. Unexpected global variables
  • 2. Forgotten timer or callback function
  • 3. Out of the DOM References to
  • 4. Closure
  • The first is because we use undeclared variables , And accidentally created a global variable , The variable is left in memory and cannot be recycled .
  • The second is that we set up setInterval Timer , And forget to cancel it , If the loop function has a reference to an external variable , Then this variable will be left in memory all the time , And can't be recycled .
  • The third scenario is that we get a DOM Reference to element , And the latter element is deleted , Because we always keep the reference to this element , So it can't be recycled .
  • The fourth case is the unreasonable use of closures , As a result, some variables are left in memory all the time .

Related information :

《JavaScript Memory leak tutorial 》

《4 class JavaScript Memory leaks and how to avoid them 》

《 Eradicate js The occurrence of four types of memory leaks in 》

《javascript Typical memory leaks and chrome How to find out 》

 following 38~46 The bar is ECMAScript 2015(ES6) The basic knowledge of the middle school entrance examination

38. ECMAScript What is it? ?

ECMAScript Is the standard for scripting languages , It means JavaScript follow ECMAScript Specification changes in standards , Because it is JavaScript The blueprint of .

ECMAScript and Javascript, It's essentially about a language , One is the name of the language itself , One is language constraints It's just invention JavaScript The man who (Netscape company ), Give it to me ECMA(European Computer Manufacturers Association), This man sets his standards , Because there were java The language , I want to emphasize that this thing is to make ECMA The rules of this man , So that's why this amazing thing was born , The name of this thing is called ECMAScript.

javaScript = ECMAScript + DOM + BOM( Self belief is a kind of generalized JavaScript)

ECMAScript what did you say? JavaScript What to do !

JavaScript( The narrow sense JavaScript) Ask about everything ECMAScript Can I do this ! I'm wrong if I can't ! Yes, I'm right !

—— A sudden sensation JavaScript Good no dignity , Why do we need to get individuals to restrain ourselves ,

That man was created, or wronged , I was created because I had to be restrained JavaScript.

39. ECMAScript 2015(ES6) What's new ?

  • Block scope
  • class
  • Arrow function
  • Template string
  • Strengthened object literal
  • Object to deconstruct
  • Promise
  • modular
  • Symbol
  • agent (proxy)Set
  • Function default parameters
  • rest And expansion

40. var,let and const What's the difference ?

var The declared variables are mounted on the window On , and let and const Declared variables will not :

 a = 100;
console.log(a,window.a); // 100 100
let b = 10;
console.log(b,window.b); // 10 undefined
const c = 1;
console.log(c,window.c); // 1 undefined

var Declaration variable has variable promotion ,let and const No variable promotion :

.log(a); // undefined ===> a Declared not assigned , Get by default undefined value
var a = 100;
console.log(b); // Report errors :b is not defined ===> Can't find b This variable
let b = 10;
console.log(c); // Report errors :c is not defined ===> Can't find c This variable
const c = 10;

let and const Declare chunk scope

(1){
var a = 100;
let b = 10;
}
console.log(a); // 100
console.log(b) // Report errors :b is not defined ===> Can't find b This variable
-------------------------------------------------------------
if(1){
var a = 100;
const c = 1;
}
console.log(a); // 100
console.log(c) // Report errors :c is not defined ===> Can't find c This variable

Under the same scope let and const Cannot declare a variable with the same name , and var Sure

 a = 100;
console.log(a); // 100
var a = 10;
console.log(a); // 10
-------------------------------------
let a = 100;
let a = 10;
// Console error :Identifier 'a' has already been declared ===> identifier a Has been declared .

Temporary deadband

 a = 100;
if(1){
a = 10;
// Exists in the current block scope a Use let/const In case of declaration , to a assignment 10 when , Only variables will be found in the current scope a,
// And then , It's not time to make a statement , So the console Error:a is not defined
let a = 1;
}

const

const a = 100;
const list = [];
list[0] = 10;
console.log(list); // [10]
const obj = {a:100};
obj.name = 'apple';
obj.a = 10000;
console.log(obj); // {a:10000,name:'apple'}

41. What is arrow function ?

The syntax of arrow function expression is more concise than function expression , And there's no one of its own this,arguments,super or new.target. Arrow function expressions are more suitable for places where anonymous functions are needed , And it cannot be used as a constructor .

var getCurrentDate = function (){
return new Date();
}
//ES6 Version
const getCurrentDate = () => new Date();

In this case ,ES5 Version has function(){} Declaration and return keyword , These two keywords are needed to create functions and return values . In arrow function version , We just need () Brackets , Unwanted return sentence , Because if we have only one expression or value to return , The arrow function will have an implicit return .

function greet(name) {
return 'Hello ' + name + '!';
}
//ES6 Version
const greet = (name) => `Hello ${name}`;
const greet2 = name => `Hello ${name}`;

We can also use the same parameters as function expressions and function declarations in arrow functions . If we have an argument in an arrow function , You can omit the parenthesis .

 getArgs = () => arguments
const getArgs2 = (...rest) => rest

Arrow function not accessible arguments object . So call the first getArgs Function throws an error . contrary , We can use rest Parameter to get all the parameters passed in the arrow function .

 data = {
result: 0,
nums: [1, 2, 3, 4, 5],
computeResult() {
// there “this” refer to “data” object
const addAll = () => {
return this.nums.reduce((total, cur) => total + cur, 0)
};
this.result = addAll();
}
};

Arrow function does not have its own this value . It captures the this value , In this example ,addAll Function will be copied computeResult Methods this value , If we declare arrow functions in the global scope , be this The value is window object .

42. What is a class? ?

class (class) Is in JS A new method of writing constructors in . It's a syntactic sugar that uses constructors , Use in the bottom is still prototype and prototype based inheritance .

function Person(firstName, lastName, age, address){
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.address = address;
}
Person.self = function(){
return this;
}
Person.prototype.toString = function(){
return "[object Person]";
}
Person.prototype.getFullName = function (){
return this.firstName + " " + this.lastName;
}
//ES6 Version
class Person {
constructor(firstName, lastName, age, address){
this.lastName = lastName;
this.firstName = firstName;
this.age = age;
this.address = address;
}
static self() {
return this;
}
toString(){
return "[object Person]";
}
getFullName(){
return `${this.firstName} ${this.lastName}`;
}
}

Override method and inherit from another class .

Employee.prototype = Object.create(Person.prototype);
function Employee(firstName, lastName, age, address, jobTitle, yearStarted) {
Person.call(this, firstName, lastName, age, address);
this.jobTitle = jobTitle;
this.yearStarted = yearStarted;
}
Employee.prototype.describe = function () {
return `I am ${this.getFullName()} and I have a position of ${this.jobTitle} and I started at ${this.yearStarted}`;
}
Employee.prototype.toString = function () {
return "[object Employee]";
}
//ES6 Version
class Employee extends Person { //Inherits from "Person" class
constructor(firstName, lastName, age, address, jobTitle, yearStarted) {
super(firstName, lastName, age, address);
this.jobTitle = jobTitle;
this.yearStarted = yearStarted;
}
describe() {
return `I am ${this.getFullName()} and I have a position of ${this.jobTitle} and I started at ${this.yearStarted}`;
}
toString() { // Overriding the "toString" method of "Person"
return "[object Employee]";
}
}

So how do we know it uses prototypes internally ?

{
}
function AnotherSomething(){
}
const as = new AnotherSomething();
const s = new Something();
console.log(typeof Something); // "function"
console.log(typeof AnotherSomething); // "function"
console.log(as.toString()); // "[object Object]"
console.log(as.toString()); // "[object Object]"
console.log(as.toString === Object.prototype.toString); // true
console.log(s.toString === Object.prototype.toString); // true

Related information :

《ECMAScript 6 Realized class, Yes JavaScript What's the point of front-end development ?》

《Class Basic syntax 》

43. What is a template string ?

The template string is in the JS A new method of creating string in . We can string templates by using backquotes .

var greet = 'Hi I\'m Mark';
//ES6 Version
let greet = `Hi I'm Mark`;

stay ES5 We need to use some escape characters to achieve multi line effect , The template string doesn't need to be so cumbersome :

var lastWords = '\n'
+ ' I \n'
+ ' Am \n'
+ 'Iron Man \n';
//ES6 Version
let lastWords = `
I
Am
Iron Man
`;

stay ES5 In the version , We need to add \n To add a new line to the string . In template string , We don't need to .

function greet(name) {
return 'Hello ' + name + '!';
}
//ES6 Version
function greet(name) {
return `Hello ${name} !`;
}

stay ES5 In the version , If you need to add an expression or value to a string , You need to use + Operator . In template string s in , We can use ${expr} Embed an expression , This makes it ES5 Cleaner version .

44. What is object deconstruction ?

Object destructor is a new way to get or extract values from objects or arrays 、 A simpler approach . Suppose you have the following objects :

 employee = {
firstName: "Marko",
lastName: "Polo",
position: "Software Developer",
yearHired: 2017
};

Get properties from object , The early method was to create a variable with the same name as the object property . This method is troublesome , Because we're going to create a new variable for each property . Suppose we have a big object , It has many properties and methods , Extracting attributes in this way can be cumbersome .

 firstName = employee.firstName;
var lastName = employee.lastName;
var position = employee.position;
var yearHired = employee.yearHired;

Using deconstruction syntax is much simpler :

{ firstName, lastName, position, yearHired } = employee;

We can also alias properties :

 { firstName: fName, lastName: lName, position, yearHired } = employee;

Of course, if the property value is undefined when , We can also specify default values :

 { firstName = "Mark", lastName: lName, position, yearHired } = employee;

45. What is? Set object , How it works ?

Set Object allows you to store unique values of any type , Whether it's the original value or the object reference .

We can use Set Constructor creation Set example .

 set1 = new Set();
const set2 = new Set(["a","b","c","d","d","e"]);

We can use add Method direction Set Add a new value to the instance , because add Method returns Set object , So we can use it again in a chained way add. If a value already exists in Set In the object , Then it will no longer be added .

set2.add();
set2.add("g").add("h").add("i").add("j").add("k").add("k");
// After a “k” Will not be added to set In the object , Because it already exists

We can use has Methods to check Set Is there a specific value in the instance .

set2.has() // true
set2.has("z") // true

We can use size Attribute gets Set Length of instance .

set2.size

have access to clear Methods to remove Set Data in .

set2.clear();

We can use Set Object to remove duplicate elements from an array .

 numbers = [1, 2, 3, 4, 5, 6, 6, 7, 8, 8, 5];
const uniqueNums = [...new Set(numbers)]; // [1,2,3,4,5,6,7,8]

And then there is WeakSet, And Set similar , It's also a set of values that don't repeat . however WeakSet Members of can only be objects , It can't be any other type of value .WeakSet The objects in are all weak references , That is, garbage collection mechanism does not consider WeakSet Reference to the object .

  • Map data structure . It's like an object , It's also a set of key value pairs , however “ key ” Is not limited to strings , Various types of values ( Including objects ) Can be used as a key .
  • WeakMap Structure and Map The structure is similar to , It is also a set used to generate key value pairs . however WeakMap Only objects are accepted as key names ( null With the exception of ), Other types of values are not accepted as key names . and WeakMap The object pointed to by the key name of , Not included in the garbage collection mechanism .

46. What is? Proxy?

Proxy Used to modify the default behavior of certain operations , It's equivalent to making changes at the language level , So it belongs to “ Metaprogramming ”, That is to program the programming language .

Proxy Can be interpreted as , Set up a layer in front of the target object “ Intercept ”, External access to the object , All must be intercepted through this layer first , So it provides a mechanism , It can filter and rewrite external access .Proxy The original meaning of this word is agent , It's used here to show that it comes from “ agent ” Some operations , It can be translated into “ Agent ”.

 High energy warning ,
following 47~64 The bar is JavaScript It is difficult to realize the advanced knowledge and related handwriting , Ladies and gentlemen, please take your time

47. Write a generic event listener function

const EventUtils = {
// Depending on your ability, use dom0||dom2||IE The way To bind events
// Add event
addEvent: function(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
// Remove events
removeEvent: function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
},
// Get the event target
getTarget: function(event) {
return event.target || event.srcElement;
},
// obtain event References to objects , Get all the information about the event , Make sure you can use event
getEvent: function(event) {
return event || window.event;
},
// Stop the incident ( It's mainly the bubbling of events , because IE Event capture is not supported )
stopPropagation: function(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
},
// Cancel the default behavior of the event
preventDefault: function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
}
};

48. What is functional programming ? JavaScript Which features of make it a candidate language for functional languages ?

Functional programming ( Commonly abbreviated as FP) By writing pure functions , Avoid sharing state 、 Variable data 、 side effect To build software . Digital programming is declarative It's not imperative Of , The state of an application flows through pure functions . Contrast with object-oriented programming , The state of an application in an object-oriented system is usually shared and coexisted with the methods in the object .

Functional programming is a programming paradigm , This means that it is based on some basic definition principles ( As listed above ) Thinking about the way of software construction . Of course , Other examples of programming paradigms include object-oriented programming and process programming .

Functional code is often simpler than imperative or object-oriented code , More predictable , Easier to test - But if you're not familiar with it and the common patterns associated with it , Functional code may also look more cluttered , also Relevant literature is not easy for new people to understand .

49. What is a higher-order function ?

Higher order functions are only functions that take functions as parameters or return values .

{
return callback(param);
}

50. Why functions are called first class citizens ?

stay JavaScript in , Functions not only have all the traditional ways of using functions ( Declaration and call ), And it can be done like a simple value :

  • assignment (var func = function(){})、
  • The ginseng (function func(x,callback){callback();})、
  • return (function(){return function(){}}),

Such a function is also called a first order function (First-class Function). More Than This ,JavaScript The function in also functions as a constructor for a class , At the same time, it's another Function Class (instance). Such multiple identities make JavaScript The function of becomes very important .

51. Manual implementation Array.prototype.map Method

map() Method to create a new array , The result is the result returned after each element in the array invokes a supplied function .

{
// First , Check that the parameters passed are correct .
if (!Array.isArray(arr) || !arr.length || typeof mapCallback !== 'function') {
return [];
} else {
let result = [];
// Every time this function is called , We will all create one result Array
// Because we don't want to change the original array .
for (let i = 0, len = arr.length; i < len; i++) {
result.push(mapCallback(arr[i], i, arr));
// take mapCallback The result returned push To result Array
}
return result;
}
}

52. Manual implementation Array.prototype.filter Method

filter() Method to create a new array , It contains all the elements of the test implemented by the provided function .

{
// First , Check that the parameters passed are correct .
if (!Array.isArray(arr) || !arr.length || typeof filterCallback !== 'function')
{
return [];
} else {
let result = [];
// Every time this function is called , We will all create one result Array
// Because we don't want to change the original array .
for (let i = 0, len = arr.length; i < len; i++) {
// Check filterCallback Is the return value of true
if (filterCallback(arr[i], i, arr)) {
// If the condition is true , Array element push To result in
result.push(arr[i]);
}
}
return result; // return the result array
}
}

53. Manual implementation Array.prototype.reduce Method

reduce() Method to execute a reducer function ( Ascending execution ), Summarize its results into a single return value .

{
// First , Check that the parameters passed are correct .
if (!Array.isArray(arr) || !arr.length || typeof reduceCallback !== 'function')
{
return [];
} else {
// If not initialValue Pass to this function , We will use the first array item as the initialValue
let hasInitialValue = initialValue !== undefined;
let value = hasInitialValue ? initialValue : arr[0];
、
// If there is a delivery initialValue, Index from 1 Start , Otherwise, from 0 Start
for (let i = hasInitialValue ? 1 : 0, len = arr.length; i < len; i++) {
value = reduceCallback(value, arr[i], i, arr);
}
return value;
}
}

54. js Deep and light copies of

JavaScript It's always been difficult to copy , If now the interviewer asked me to write a deep copy , I might just be able to write a basic version of . So before I wrote this, I read the blog posts written by all kinds of big men in my favorites . You can see the link I posted below , Here's just a brief summary .

  • Shallow copy : Create a new object , This object has an exact copy of the original object property values . If the attribute is a basic type , The copied values are the basic types , If the property is a reference type , Copy is the memory address , So if one of the objects changes the address , It will affect another object .
  • Deep copy : A complete copy of an object from memory , Open up a new area of heap memory for new objects , And modifying the new object does not affect the original object .

The implementation of shallow copy :

  • Object.assign() Method : Used to copy the values of all enumerated attributes from one or more source objects to the target object . It will return the target object .
  • **Array.prototype.slice():**slice() Method returns a new array object , This object is made up of begin and end( barring end) Determine the shallow copy of the original array . The original array will not be changed .
  • Extension operators ...
 a = {
name: "Jake",
flag: {
title: "better day by day",
time: "2020-05-31"
}
}
let b = {...a};

The implementation of deep copy :

  • The beggar version : JSON.parse(JSON.stringify(object)), There are many shortcomings ( Will ignore undefined、symbol、 function ; Can't solve circular references ; Can't handle regular 、new Date())
  • Basic Edition ( Interview enough ): Shallow copy + recursive ( Only the ordinary object and array Two types of data )
{
if(typeOf taret ==='object'){
let cloneTarget = Array.isArray(target) ? [] : {};
if(map.get(target)) {
return target;
}
map.set(target, cloneTarget);
for(const key in target){
cloneTarget[key] = cloneDeep(target[key], map);
}
return cloneTarget
}else{
return target
}
}
  • ultimate :
 mapTag = '[object Map]';
const setTag = '[object Set]';
const arrayTag = '[object Array]';
const objectTag = '[object Object]';
const argsTag = '[object Arguments]';
const boolTag = '[object Boolean]';
const dateTag = '[object Date]';
const numberTag = '[object Number]';
const stringTag = '[object String]';
const symbolTag = '[object Symbol]';
const errorTag = '[object Error]';
const regexpTag = '[object RegExp]';
const funcTag = '[object Function]';
const deepTag = [mapTag, setTag, arrayTag, objectTag, argsTag];
function forEach(array, iteratee) {
let index = -1;
const length = array.length;
while (++index < length) {
iteratee(array[index], index);
}
return array;
}
function isObject(target) {
const type = typeof target;
return target !== null && (type === 'object' || type === 'function');
}
function getType(target) {
return Object.prototype.toString.call(target);
}
function getInit(target) {
const Ctor = target.constructor;
return new Ctor();
}
function cloneSymbol(targe) {
return Object(Symbol.prototype.valueOf.call(targe));
}
function cloneReg(targe) {
const reFlags = /\w*$/;
const result = new targe.constructor(targe.source, reFlags.exec(targe));
result.lastIndex = targe.lastIndex;
return result;
}
function cloneFunction(func) {
const bodyReg = /(?<={)(.|\n)+(?=})/m;
const paramReg = /(?<=\().+(?=\)\s+{)/;
const funcString = func.toString();
if (func.prototype) {
const param = paramReg.exec(funcString);
const body = bodyReg.exec(funcString);
if (body) {
if (param) {
const paramArr = param[0].split(',');
return new Function(...paramArr, body[0]);
} else {
return new Function(body[0]);
}
} else {
return null;
}
} else {
return eval(funcString);
}
}
function cloneOtherType(targe, type) {
const Ctor = targe.constructor;
switch (type) {
case boolTag:
case numberTag:
case stringTag:
case errorTag:
case dateTag:
return new Ctor(targe);
case regexpTag:
return cloneReg(targe);
case symbolTag:
return cloneSymbol(targe);
case funcTag:
return cloneFunction(targe);
default:
return null;
}
}
function clone(target, map = new WeakMap()) {
// Clone the original type
if (!isObject(target)) {
return target;
}
// initialization
const type = getType(target);
let cloneTarget;
if (deepTag.includes(type)) {
cloneTarget = getInit(target, type);
} else {
return cloneOtherType(target, type);
}
// Prevent circular references
if (map.get(target)) {
return map.get(target);
}
map.set(target, cloneTarget);
// clone set
if (type === setTag) {
target.forEach(value => {
cloneTarget.add(clone(value, map));
});
return cloneTarget;
}
// clone map
if (type === mapTag) {
target.forEach((value, key) => {
cloneTarget.set(key, clone(value, map));
});
return cloneTarget;
}
// Clone objects and arrays
const keys = type === arrayTag ? undefined : Object.keys(target);
forEach(keys || target, (value, key) => {
if (keys) {
key = value;
}
cloneTarget[key] = clone(target[key], map);
});
return cloneTarget;
}
module.exports = {
clone
};

Reference article :

How to write a deep copy of an amazing interviewer

The ultimate exploration of deep copy (99% People don't know )

55. Handwriting call、apply And bind function

call Function implementation steps :

  • 1. Determine whether the calling object is a function , Even if we are defined on the prototype of a function , But the use of call And so on .
  • 2. Determine whether the incoming context object exists , If it doesn't exist , Is set to window .
  • 3. Process incoming parameters , Intercept all parameters after the first parameter .
  • 4. Use the function as an attribute of the context object .
  • 5. Use the context object to call this method , And save the returned results .
  • 6. Delete the newly added attribute .
  • 7. Return results .
Function.prototype.myCall = function(context) {
// Judge the calling object
if (typeof this !== "function") {
console.error("type error");
}
// To obtain parameters
let args = [...arguments].slice(1),
result = null;
// Judge context Whether to introduce , If it is not passed in, it is set to window
context = context || window;
// Methods that make the calling function an object
context.fn = this;
// Call function
result = context.fn(...args);
// Delete attribute
delete context.fn;
return result;
};

apply Function implementation steps :

    1. Determine whether the calling object is a function , Even if we are defined on the prototype of a function , But the use of call And so on .
    1. Determine whether the incoming context object exists , If it doesn't exist , Is set to window .
    1. Use the function as an attribute of the context object .
    1. Determine whether the parameter value is passed in
    1. Use the context object to call this method , And save the returned results .
    1. Delete the newly added attribute
    1. Return results
Function.prototype.myApply = function(context) {
// Determine whether the calling object is a function
if (typeof this !== "function") {
throw new TypeError("Error");
}
let result = null;
// Judge context Whether there is , If not, it is window
context = context || window;
// Methods that make functions objects
context.fn = this;
// Calling method
if (arguments[1]) {
result = context.fn(...arguments[1]);
} else {
result = context.fn();
}
// Delete attribute
delete context.fn;
return result;
};

bind Function implementation steps :

  • 1. Determine whether the calling object is a function , Even if we are defined on the prototype of a function , But the use of call And so on .
  • 2. Save a reference to the current function , Get the rest of the incoming parameter values .
  • 3. Create a function that returns
  • 4. Function internal use apply To bind function calls , You need to judge the function as a constructor , At this time, you need to pass in the current function this to apply call , The rest is passed in to the specified context object .
Function.prototype.myBind = function(context) {
// Determine whether the calling object is a function
if (typeof this !== "function") {
throw new TypeError("Error");
}
// To obtain parameters
var args = [...arguments].slice(1),
fn = this;
return function Fn() {
// According to the way it is called , Pass in different binding values
return fn.apply(
this instanceof Fn ? this : context,
args.concat(...arguments)
);
};
};

Reference article :《 Handwriting call、apply And bind function 》

《JavaScript In depth call and apply Simulation Implementation of 》

56. The realization of function coritization

function curry(fn, args) {
// Get the parameter length required by the function
let length = fn.length;
args = args || [];
return function() {
let subArgs = args.slice(0);
// Splicing to get all the existing parameters
for (let i = 0; i < arguments.length; i++) {
subArgs.push(arguments[i]);
}
// Determine whether the length of the parameter has met the length of the parameter required by the function
if (subArgs.length >= length) {
// If meet , Execute function
return fn.apply(this, subArgs);
} else {
// If not satisfied , Recursively returns the corized function , Wait for the parameter to pass in
return curry.call(this, fn, subArgs);
}
};
}
// es6 Realization
function curry(fn, ...args) {
return fn.length <= args.length ? fn(...args) : curry.bind(null, fn, ...args);
}

Reference article :《JavaScript Currization of thematic functions 》

57. js simulation new The implementation of the operator

This question, if you search the Nuggets , You may find answers like this :

Tell the truth , For the first time , I don't understand , I need to go through the prototype and prototype chain to understand . So I think MDN Yes new The explanation is easier to understand :

new Operator to create an instance of a user-defined object type or a built-in object with a constructor .new The keyword will do the following :

  1. Create an empty simple JavaScript object ( namely {});
  2. Link the object ( That is, set the constructor of the object ) To another object ;
  3. Will step 1 The newly created object serves as this The context of ;
  4. If the function does not return an object , Then return to this.

Now let's look at implementation :

{
this.name = name;
this.color = color;
this.age = age;
}
Dog.prototype={
getName: function() {
return this.name
}
}
var dog = new Dog(' rhubarb ', 'yellow', 3)

I believe the above code does not need to explain , We all know . Let's take a look at the last line new Keyword code , According to the above 1,2,3,4 Step by step new The operation behind it .

First step : Create a simple empty object

 obj = {}

The second step : Link this object to another object ( Prototype chain )

obj.__proto__ = Dog.prototype

The third step : Will step 1 The newly created object serves as this The context of

Dog.apply(obj, [' rhubarb ', 'yellow', 3])

Step four : If the function does not return an object , Then return to this

var dog = obj
dog.getName() // ' rhubarb '

It should be noted that if Dog() Yes return Then return to return Value

 rtnObj = {}
function Dog(name, color, age) {
// ...
// Return an object
return rtnObj
}
var dog = new Dog(' rhubarb ', 'yellow', 3)
console.log(dog === rtnObj) // true

Next, we encapsulate the above steps into an object instantiation method , That is simulation new The operation of :

{
var obj = {};
// Gets the first parameter of the method ( And delete the first parameter ), This parameter is a constructor
var Constructor = [].shift.apply(arguments);
// Set the internal properties of the new object __proto__ Point to the prototype of the constructor , This allows the new object to access the properties and methods in the prototype
obj.__proto__ = Constructor.prototype;
// Get the return value of the constructor
var ret = Constructor.apply(obj, arguments);
// If the return value is an object, return that object , Otherwise, an instance object of the constructor is returned
return typeof ret === "object" ? ret : obj;
}

58. What is a callback function ? What's wrong with callback functions

Callback function Is an executable code segment , It is passed to other code as a parameter , Its function is to call this paragraph when necessary ( Callback function ) Code .

stay JavaScript Middle function is also a kind of object , The same object can be passed as an argument to a function , So a function can also be passed as an argument to another function , This function as an argument is a callback function .

 btnAdd = document.getElementById('btnAdd');
btnAdd.addEventListener('click', function clickCallback(e) {
// do something useless
});

In this case , We are waiting for id by btnAdd Of the click event , If it is clicked , execute clickCallback function . Callback functions add functions to certain data or events .

The callback function has a fatal weakness , It's easy to write back to hell (Callback hell). Suppose that multiple events have dependencies :

(() => {
console.log(1)
setTimeout(() => {
console.log(2)
setTimeout(() => {
console.log(3)
},3000)
},2000)
},1000)

This is the typical callback hell , The above code seems to be hard to read and maintain , Once there are more incidents, it will be even more chaotic , So in es6 In the proposed Promise and async/await To solve the problem of callback to hell . Of course , The callback function has several other drawbacks , For example, you can't use try catch Capture the error , Not directly return. Here are the next two questions , Let's look down .

59. Promise What is it? , Can you do it by hand ?

Promise, It's a promise , Promise it will give you a result in a period of time . In terms of programming Promise Is a solution to asynchronous programming . Here is Promise stay MDN Description of :

Promise Object is a proxy object ( Agent a value ), The value of being represented is Promise Object creation may be unknown . It allows you to bind the corresponding processing methods for the success and failure of asynchronous operation (handlers). This allows asynchronous methods to return values like synchronous methods , But it doesn't immediately return the final execution result , It's a result that represents the future promise object .

One Promise There are several States :

  • pending: The initial state , It's not a success , It's not a failure .
  • fulfilled: Means the operation is completed successfully .
  • rejected: Means the operation failed .

Once this commitment changes from waiting state to other state, it can never change state , That is to say, once the state becomes fulfilled/rejected after , Can't change again . Maybe we don't understand the concept Promise, Let's take a simple chestnut ;

If I had a girlfriend , Next Monday is her birthday , I promised her a surprise for her birthday , So from now on, this commitment will be in the waiting state , Waiting for next Monday , Then the state changes . If I give my girlfriend a surprise next Monday , Then the state of the commitment will be pending Switch to a fulfilled, It means that the promise has been fulfilled successfully , Once that happens , There would be no more results , That is, the state is not going to change ; On the contrary, if I work overtime because I am too busy , Forget about it , The promised surprise didn't materialize , The state will be from pending Switch to a rejected, Time can't be reversed , So the state can no longer change .

The last one we said Promise Can solve the problem of callback to hell , you 're right ,pending State of Promise Object will trigger fulfilled/rejected state , Once the status changes ,Promise Object's then Method will be called ; Otherwise it will trigger catch. Let's rewrite the previous code calling back to hell :

 Promise((resolve,reject) => {
setTimeout(() => {
console.log(1)
resolve()
},1000)
}).then((res) => {
setTimeout(() => {
console.log(2)
},2000)
}).then((res) => {
setTimeout(() => {
console.log(3)
},3000)
}).catch((err) => {
console.log(err)
})

Actually Promise There are also some shortcomings , For example, it can't be cancelled Promise, Errors need to be captured by callback functions .

promise Handwritten implementation , Interview is enough :

{
let self=this;
self.status="pending" // Define the initial state before the state changes
self.value=undefined;// Define status as resolved The state of being
self.reason=undefined;// Define status as rejected The state of being
function resolve(value){
// Two ==="pending", Ensures that the change of state is irreversible
if(self.status==="pending"){
self.value=value;
self.status="resolved";
}
}
function reject(reason){
// Two ==="pending", Ensures that the change of state is irreversible
if(self.status==="pending"){
self.reason=reason;
self.status="rejected";
}
}
// Capture structural anomalies
try{
constructor(resolve,reject);
}catch(e){
reject(e);
}
}
// Defines the chain call then Method
myPromise.prototype.then=function(onFullfilled,onRejected){
let self=this;
switch(self.status){
case "resolved":
onFullfilled(self.value);
break;
case "rejected":
onRejected(self.reason);
break;
default:
}
}

About Promise There are other things , such as Promise.all()、Promise.race() The use of etc , Because of the space, we don't do it anymore , For a deeper understanding, please see the following article .

Related information :

「 hardcore JS」 Learn more about asynchronous solutions

【 translate 】Promises/A+ standard

60. Iterator What is it? , What's the role ?

Iterator It's understanding the first 61 The prerequisite knowledge of article , Maybe it's me IQ Not enough ?,Iterator and Generator After watching it many times, I still know nothing about it , Even if I understood , After a while, I forgot everything ...

Iterator( iterator ) It's an interface , It can also be said to be a norm . Provide unified access mechanism for different data structures . Any data structure only needs to be deployed Iterator Interface , You can complete the traversal operation ( That is, all members of the data structure are processed in turn ).

Iterator grammar :

 obj = {
[Symbol.iterator]:function(){}
}

[Symbol.iterator] Attribute names are written in a fixed way , As long as the object that owns the property , We can traverse it in the way of iterators .

Iterator traversal method is to first get an iterator pointer , Initially, the pointer points before the first data , Then by calling next Method , Change the direction of the pointer , Let it point to the next piece of data Every time next Will return an object , The object has two properties

  • value Represents the data you want to get
  • done Boolean value ,false Indicates that the data pointed to by the current pointer has a value ,true Indicates that the traversal is over

Iterator There are three functions of :

  1. For a variety of data structures , Provide a unified 、 Simple access interface ;
  2. Enables members of a data structure to be arranged in a certain order ;
  3. ES6 Creates a new traversal command for…of loop ,Iterator Main interface supply for…of consumption .

Ergodic process :

  1. Create a pointer object , Point to the start of the current data structure . in other words , Ergodic objects are essentially , It's a pointer object .
  2. The first call to the next Method , You can point a pointer to the first member of a data structure .
  3. The second call to the next Method , Pointer to the second member of the data structure .
  4. Calling the pointer object's next Method , Until it points to the end of the data structure .

Every time you call next Method , Will return information about the current member of the data structure . say concretely , Is to return a containing value and done Objects with two properties . among ,value Property is the value of the current member ,done Property is a Boolean value , Indicates whether the traversal ends .

 arr = [{num:1},2,3]
let it = arr[Symbol.iterator]() // Get the iterator in the array
console.log(it.next()) // { value: Object { num: 1 }, done: false }
console.log(it.next()) // { value: 2, done: false }
console.log(it.next()) // { value: 3, done: false }
console.log(it.next()) // { value: undefined, done: true }

61. Generator What is a function , What's the role ?

Generator Function can be said to be Iterator Specific implementation of the interface .Generator The biggest feature is that it can control the execution of functions .

{
let y = 2 * (yield (x + 1))
let z = yield (y / 3)
return (x + y + z)
}
let it = foo(5)
console.log(it.next()) // => {value: 6, done: false}
console.log(it.next(12)) // => {value: 8, done: false}
console.log(it.next(13)) // => {value: 42, done: true}

The above example is a Generator function , Let's analyze the execution process :

  • First Generator When a function is called, it returns an iterator
  • When executing the first time next when , The conference was ignored , And the function pauses in yield (x + 1) It's about , So back 5 + 1 = 6
  • When executing the second next when , The parameter passed in is equal to the previous one yield The return value of , If you don't pass it on ,yield Never return undefined. here let y = 2 * 12, So the second one yield be equal to 2 * 12 / 3 = 8
  • When executing the third time next when , The parameters passed in are passed to z, therefore z = 13, x = 5, y = 24, The sum is equal to 42

Generator Functions are rarely seen , In fact, it has something to do with him , And they usually cooperate with co Library to use . Of course , We can go through Generator Function to solve the problem of callback hell .

62. What is? async/await And how it works , What are the advantages and disadvantages ?

async/await It is based on Promise A new way to write asynchronous or non blocking code , It is generally believed that JS The ultimate and most elegant solution to asynchronous operations . be relative to Promise And callback , It is more readable and concise . After all, it's been then() I'm upset .

async Asynchronous means , and await yes async wait Abbreviation , Asynchronous waiting .

So it's easy to understand semantically async Used to declare a function It's asynchronous , and await Used to wait for an asynchronous method execution to complete .

A function if you add async , Then the function will return a Promise

async function test() {
return "1"
}
console.log(test()) // -> Promise {<resolved>: "1"}

You can see that the output is a Promise object . therefore ,async The function returns a Promise object , If in async Direct in function return A direct measure ,async I will measure this directly through PromIse.resolve() Encapsulated into Promise Object returns .

Compared with Promise,async/await Can handle... Better then chain

{
return new Promise(resolve => {
setTimeout(() => resolve(n + 200), n);
});
}
function step1(n) {
console.log(`step1 with ${n}`);
return takeLongTime(n);
}
function step2(n) {
console.log(`step2 with ${n}`);
return takeLongTime(n);
}
function step3(n) {
console.log(`step3 with ${n}`);
return takeLongTime(n);
}

Now we use Promise and async/await To achieve the three steps of processing .

Use Promise

{
console.time("doIt");
const time1 = 300;
step1(time1)
.then(time2 => step2(time2))
.then(time3 => step3(time3))
.then(result => {
console.log(`result is ${result}`);
});
}
doIt();
// step1 with 300
// step2 with 500
// step3 with 700
// result is 900

Use async/await

async function doIt() {
console.time("doIt");
const time1 = 300;
const time2 = await step1(time1);
const time3 = await step2(time2);
const result = await step3(time3);
console.log(`result is ${result}`);
}
doIt();

The result is the same as before Promise The implementation is the same , But the code doesn't look much clearer , Elegant and neat , It's almost like synchronous code .

await Keywords can only be found in async function Use in . In any non async function Used in await Keywords throw errors .await Keyword waits for the right expression before executing the next line of code ( It could be a Promise) return .

Advantages and disadvantages :

async/await The advantage is to deal with then The call chain of , Be able to write code more clearly and accurately , And it also gracefully solves the callback hell problem . Of course, there are some disadvantages , because await Transform asynchronous code into synchronous code , If more than one asynchronous code is used without dependency await Will lead to performance degradation .

Reference article :

「 hardcore JS」 Learn more about asynchronous solutions

above 21~25 The rule is JavaScript The main asynchronous solution in , There are difficulties , It needs to be studied and practiced .

63. instanceof What is the principle of , How to achieve

instanceof Can correctly judge the type of object , Because the internal mechanism is to determine whether the type can be found in the prototype chain of the object prototype.

Realization instanceof:

 First get the prototype of the type
 And then get the prototype of the object
 And then we loop through to determine whether the prototype of the object is equal to the prototype of the type , Until the object prototype is null, Because the prototype chain is ultimately null
{
let prototype = right.prototype
left = left.__proto__
while (true) {
if (left === null || left === undefined)
return false
if (prototype === left)
return true
left = left.__proto__
}
}

64. js Throttling and anti chattering

Function anti shake When an event is triggered n Seconds before the callback , If in this n The second event is triggered again , Then the time will be counted again . This can be used on some click request events , Avoid sending multiple requests to the back end because of the user's multiple clicks .

Function throttling It means to set a unit time , In this unit time , There can only be a callback function that triggers an event once , If an event is triggered multiple times in the same unit time , Only once can it work . Throttling can be used in scroll Function event monitoring , Reduce the frequency of event calls through event throttling .

function debounce(fn, wait) {
var timer = null;
return function() {
var context = this,
args = arguments;
// If there is a timer at this point , Then cancel the previous timer and record the time again
if (timer) {
clearTimeout(timer);
timer = null;
}
// Set the timer , Causes the event interval to be executed after the specified event
timer = setTimeout(() => {
fn.apply(context, args);
}, wait);
};
}
// The realization of function throttling ;
function throttle(fn, delay) {
var preTime = Date.now();
return function() {
var context = this,
args = arguments,
nowTime = Date.now();
// If the interval between two times exceeds the specified time , Then execute the function .
if (nowTime - preTime >= delay) {
preTime = Date.now();
return fn.apply(context, args);
}
};
}

For details, please refer to :

《 Easy to understand JS Function throttling and function buffeting 》

《JavaScript Event throttling and event buffeting 》

《JS Anti shake and throttling 》

65. What is design pattern ?

1. Concept

Design patterns are a set of things that are used repeatedly 、 Most people know that 、 Catalogued 、 Summary of code design experience . Design patterns are used to reuse code 、 Make code easier to understand 、 Ensure code reliability . without doubt , Design patterns win more than others and systems , Design patterns make coding really Engineering , Design patterns are the foundation of software engineering , It's like bricks and stones in a building .

2. Design principles

  1. S – Single Responsibility Principle Principle of single responsibility
    • A program does only one thing
    • If the function is too complex, it should be separated , Each part remains independent
  2. O – OpenClosed Principle to open up / Closed principle
    • Open to expansion , Closed to modification
    • When increasing demand , Extend new code , Instead of modifying existing code
  3. L – Liskov Substitution Principle Richter's principle of substitution
    • A subclass can cover a superclass
    • Where the parent class can appear, the child class can appear
  4. I – Interface Segregation Principle Interface isolation principle
    • Keep the interface single and independent
    • Similar to the principle of single responsibility , This is more about the interface
  5. D – Dependency Inversion Principle Dependence Inversion Principle
    • Interface oriented programming , Depend on abstraction and not on having
    • The user only pays attention to the interface but not the implementation of the concrete class

3. The type of design pattern

  1. Structural mode (Structural Patterns): Simplify the design of the system by identifying the simple relationships between the components in the system .
  2. Create pattern (Creational Patterns): Handle the creation of objects , Create objects in the right way according to the actual situation . Regular object creation may lead to design problems , Or increase the complexity of the design . The creation pattern solves the problem by controlling the creation of objects in some way .
  3. Behavioral patterns (Behavioral Patterns): It is used to identify and implement common interaction patterns between objects , such , Increased the flexibility of these interactions .

66. 9 A common design pattern for the front end

1. Appearance mode (Facade Pattern)

Appearance pattern is one of the most common design patterns , It provides a unified high-level interface for a group of interfaces in the subsystem , Make the subsystem easier to use . In short, the appearance design pattern is to abstract the complex logic in multiple subsystems , To provide a more unified 、 More concise 、 Easier to use API. Many of the frameworks and libraries we use basically follow the design pattern , such as JQuery Just take the complex primordial DOM Operations are abstracted and encapsulated , And eliminate the compatibility problem between browsers , This provides a more advanced and easy to use version . In fact, in our daily work, we often use appearance pattern for development , It's just that we don't know it .

 Compatible with browser event binding
 addMyEvent = function (el, ev, fn) {
if (el.addEventListener) {
el.addEventListener(ev, fn, false)
} else if (el.attachEvent) {
el.attachEvent('on' + ev, fn)
} else {
el['on' + ev] = fn
}
};
 Encapsulation interface
 myEvent = {
// ...
stop: e => {
e.stopPropagation();
e.preventDefault();
}
};

scene

  • At the beginning of design , There should be a conscious separation of the two different layers , For example, the classic three-tier structure , In the data access layer and business logic layer 、 Create appearance between business logic layer and presentation layer Facade
  • In the development stage , Subsystems tend to become more and more complex due to constant reconfiguration and evolution , Add appearance Facade Can provide a simple interface , Reduce their dependence on each other .
  • When maintaining a large legacy system , Maybe this system is hard to maintain , Now use the look Facade It's also very suitable , Develop a look for the system Facade class , It provides a clear interface for designing rough and highly complex legacy code , Let the new system and Facade Object interaction ,Facade Interact with legacy code for all the complex work .

advantage

  • Reduce system interdependence .
  • Increase flexibility .
  • Improved security

shortcoming

  • Inconsistent with the open and close principle , It's hard to change things , Inheritance rewriting is not appropriate .

2. The proxy pattern (Proxy Pattern)

Is to provide a substitute or a place holder for an object , In order to control access to it

“ Suppose that A Receive flowers when you are in a good mood , Xiao Ming's chances of success are

60%, And when A Get flowers when you're in a bad mood , The success rate of Xiaoming's confession is infinitely close to 0. Xiao Ming and A I just met for two days , It's impossible to tell A When are you in a good mood . If you give flowers out of time A, flowers It's very likely to be thrown away , Xiao Ming ate this bunch of flowers 7 In exchange for instant noodles . however A Friend, B But I know A, So Xiao Ming just gave the flowers to B,B Will listen A The mood change of , Then choose Choose A Hand over the flowers to when you are in a good mood A, The code is as follows :

 Flower = function() {}
let xiaoming = {
sendFlower: function(target) {
let flower = new Flower()
target.receiveFlower(flower)
}
}
let B = {
receiveFlower: function(flower) {
A.listenGoodMood(function() {
A.receiveFlower(flower)
})
}
}
let A = {
receiveFlower: function(flower) {
console.log(' Get the flowers '+ flower)
},
listenGoodMood: function(fn) {
setTimeout(function() {
fn()
}, 1000)
}
}
xiaoming.sendFlower(B)

scene

  • HTML element Prime event agent
 <li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
let ul = document.querySelector('#ul');
ul.addEventListener('click', event => {
console.log(event.target);
});
</script>
  • ES6 Of proxy Ruan Yifeng Proxy
  • jQuery.proxy() Method

advantage

  • The proxy pattern separates the proxy object from the called object , Reduce the coupling degree of the system . The proxy pattern acts as a mediator between the client and the target object , This can protect the target object
  • The proxy object can extend the function of the target object ; By modifying the proxy object , Comply with opening and closing principle ;

shortcoming

  • There may be differences in the speed of processing requests , Indirect access has overhead

3. Factory mode (Factory Pattern)

The factory pattern defines an interface for creating objects , This interface is determined by subclasses which class to instantiate . This pattern delays the instantiation of a class to subclasses . Subclasses can override interface methods to specify their own object types when they are created .

{
constructor(name) {
this.name = name
}
init() {
console.log('init')
}
fun() {
console.log('fun')
}
}
class Factory {
create(name) {
return new Product(name)
}
}
// use
let factory = new Factory()
let p = factory.create('p1')
p.init()
p.fun()

scene

  • If you don't want a strong coupling between a subsystem and a larger object , It's about choosing from many subsystems at runtime , So the factory model is an ideal choice
  • take new It's easy to operate and encapsulate , encounter new We should consider whether to use the factory mode ;
  • You need to rely on the specific environment to create different instances , These examples all have the same behavior , In this case, we can use the factory mode , Simplify the process of implementation , It also reduces the amount of code required for each object , It helps to eliminate the coupling between objects , Provide more flexibility

advantage

  • The process of creating objects can be complex , But we just need to care about creating results .
  • The constructor is separated from the Creator , accord with “ Opening and closing principle ”
  • A caller wants to create an object , Just know its name .
  • High expansibility , If you want to add a product , Just extend a factory class .

shortcoming

  • When adding a new product , New product-specific classes need to be written , To some extent, it increases the complexity of the system
  • Considering the scalability of the system , You need to introduce an abstraction layer , The client code is defined using an abstraction layer , Increases the abstractness of the system and the difficulty of understanding

When not to

  • When applied to the wrong problem type , The first mock exam will introduce a lot of unnecessary complexity to the application . Unless providing an interface for creating objects is a design goal of the library or framework we write , Otherwise, I would suggest using explicit constructors , To avoid unnecessary expenses .
  • Due to the fact that the object creation process is efficiently abstracted behind an interface , It also raises questions about how complex unit testing can be depending on the process .

4. The singleton pattern (Singleton Pattern)

seeing the name of a thing one thinks of its function , In singleton mode Class The maximum number of instances of is 1. When you need an object to perform certain tasks throughout the system , The singleton pattern comes in handy . In addition, the use of singleton mode should be avoided in other scenarios , Because singleton mode introduces global state , A healthy system should avoid introducing too many global states .

To implement the singleton pattern, we need to solve the following problems :

  • How to determine the Class There is only one example ?
  • How easy to access Class The only example of ?
  • Class How to control the instantiation process ?
  • How to integrate Class The number of instances of is limited to 1?

We usually solve the above problems by implementing the following two points :

  • hide Class Constructor for , Avoid multiple instantiations
  • By exposing a getInstance() Method to create / Get the only instance

Javascript The singleton pattern can be implemented in the following ways :

const FooServiceSingleton = (function () {
// Hidden Class Constructor for
function FooService() {}
// Uninitialized singleton object
let fooService;
return {
// establish / Function to get singleton object
getInstance: function () {
if (!fooService) {
fooService = new FooService();
}
return fooService;
}
}
})();

The key points are :

  1. Use IIFE Create a local scope and execute it immediately ;
  2. getInstance() For one Closure , Use closures to save singleton objects in the local scope and return .

We can verify that the singleton object was created successfully :

 fooService1 = FooServiceSingleton.getInstance();
const fooService2 = FooServiceSingleton.getInstance();
console.log(fooService1 === fooService2); // true

Scene example

  • Define a namespace and implement branching methods
  • Login box
  • vuex and redux Medium store

advantage

  • Partitioning the namespace , Reduce global variables
  • Enhance modularity , Organize your code under a global variable name , Put it in a single place , Easy to maintain
  • And it will only be instantiated once . Simplified code debugging and maintenance

shortcoming

  • Because singleton mode provides a single point of access , So it may lead to strong coupling between modules
  • This is detrimental to unit testing . You cannot test a class that calls a method from a singleton alone , It can only be regarded as one with the singleton
  • Units tested together .

5. The strategy pattern (Strategy Pattern)

The simple description of the strategy pattern is : The object has some behavior , But in different scenarios , There are different implementation algorithms for this behavior . Encapsulate them one by one , And make them interchangeable

<head>
<title> The strategy pattern - Checklists </title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
</head>
<body>
<form id = "registerForm" method="post" action="http://xxxx.com/api/register">
user name :<input type="text" name="userName">
password :<input type="text" name="password">
Phone number :<input type="text" name="phoneNumber">
<button type="submit"> Submit </button>
</form>
<script type="text/javascript">
// Policy object
const strategies = {
isNoEmpty: function (value, errorMsg) {
if (value === '') {
return errorMsg;
}
},
isNoSpace: function (value, errorMsg) {
if (value.trim() === '') {
return errorMsg;
}
},
minLength: function (value, length, errorMsg) {
if (value.trim().length < length) {
return errorMsg;
}
},
maxLength: function (value, length, errorMsg) {
if (value.length > length) {
return errorMsg;
}
},
isMobile: function (value, errorMsg) {
if (!/^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|17[7]|18[0|1|2|3|5|6|7|8|9])\d{8}$/.test(value)) {
return errorMsg;
}
}
}
// Validation class
class Validator {
constructor() {
this.cache = []
}
add(dom, rules) {
for(let i = 0, rule; rule = rules[i++];) {
let strategyAry = rule.strategy.split(':')
let errorMsg = rule.errorMsg
this.cache.push(() => {
let strategy = strategyAry.shift()
strategyAry.unshift(dom.value)
strategyAry.push(errorMsg)
return strategies[strategy].apply(dom, strategyAry)
})
}
}
start() {
for(let i = 0, validatorFunc; validatorFunc = this.cache[i++];) {
let errorMsg = validatorFunc()
if (errorMsg) {
return errorMsg
}
}
}
}
// Calling code
let registerForm = document.getElementById('registerForm')
let validataFunc = function() {
let validator = new Validator()
validator.add(registerForm.userName, [{
strategy: 'isNoEmpty',
errorMsg: ' The user name cannot be empty '
}, {
strategy: 'isNoSpace',
errorMsg: ' Names with white space characters are not allowed '
}, {
strategy: 'minLength:2',
errorMsg: ' User name length cannot be less than 2 position '
}])
validator.add(registerForm.password, [ {
strategy: 'minLength:6',
errorMsg: ' Password length cannot be less than 6 position '
}])
validator.add(registerForm.phoneNumber, [{
strategy: 'isMobile',
errorMsg: ' Please enter the correct mobile phone number format '
}])
return validator.start()
}
registerForm.onsubmit = function() {
let errorMsg = validataFunc()
if (errorMsg) {
alert(errorMsg)
return false
}
}
</script>
</body>
</html>

Scene example

  • If there are many classes in a system , The only difference between them is their ' Behavior ', Then using the policy pattern can dynamically let an object choose a behavior among many behaviors .
  • A system needs to dynamically choose one of several algorithms .
  • Form validation

advantage

  • Use combination 、 entrust 、 Polymorphism and other technologies and ideas , It can effectively avoid multiple conditional choice statements
  • Provides access to - The perfect support of the closed principle , Encapsulate the algorithm in a separate strategy in , Make them easy to switch , understand , extensible
  • Use composition and delegation to make Context Have the ability to execute algorithms , It's also a lighter alternative to inheritance

shortcoming

  • Many policy classes or policy objects will be added to the program
  • To use the strategy pattern , You have to know all about strategy, You have to know all of them strategy The difference between , So that we can choose the right one strategy

6. Iterator pattern (Iterator Pattern)

If you see this ,ES6 Iterators in Iterator I believe you still have some impression , The above first 60 The article has already made a brief introduction . The iterator pattern simply provides a method order for aggregating the elements of an object , Without exposing the internal representation of the object .

The iterator pattern solves the following problems :

  • Provides a consistent way to traverse various data structures , Without knowing the internal structure of the data
  • Provides traversal containers ( aggregate ) Without changing the container's interface

An iterator usually needs to implement the following interfaces :

  • hasNext(): Determine whether the iteration is over , return Boolean
  • next(): Find and return to the next element

by Javascript An iterator can be written like this :

 item = [1, 'red', false, 3.14];
function Iterator(items) {
this.items = items;
this.index = 0;
}
Iterator.prototype = {
hasNext: function () {
return this.index < this.items.length;
},
next: function () {
return this.items[this.index++];
}
}

Verify that the iterator works :

 iterator = new Iterator(item);
while(iterator.hasNext()){
console.log(iterator.next());
}
// Output :1, red, false, 3.14

ES6 Provides a simpler iteration loop syntax for...of, The premise of using this syntax is that the operation object needs to implement Iterative protocol (The iterable protocol), In short, the object has a Key by Symbol.iterator Methods , This method returns a iterator object .

For example, we implement a Range Class is used to iterate over a range of numbers :

{
return {
[Symbol.iterator]: function () {
return {
next() {
if (start < end) {
return { value: start++, done: false };
}
return { done: true, value: end };
}
}
}
}
}

Check it out :

 (num of Range(1, 5)) {
console.log(num);
}
// Output :1, 2, 3, 4

7. Observer mode (Observer Pattern)

Observer mode also called Release - A subscription model (Publish/Subscribe Pattern), It's a design pattern that we're often exposed to , Applications in daily life can also be found everywhere , For example, you subscribe to a blogger's Channel , When there's a content update, you get a push ; And such as JavaScript Event subscription response mechanism in . The idea of the observer pattern can be described in one sentence as : The object of observation (subject) Maintain a group of observers (observer), When the state of the observed object changes , Notify the observer of these changes by calling one of the observer's methods .

In observer mode Subject Objects generally need to implement the following API:

  • subscribe(): Receive an observer observer object , Make it subscribe to itself
  • unsubscribe(): Receive an observer observer object , Make it unsubscribe itself
  • fire(): Triggering event , Inform all observers

use JavaScript Manually implement observer mode :

function Subject() {
this.observers = [];
}
Subject.prototype = {
// subscribe
subscribe: function (observer) {
this.observers.push(observer);
},
// Unsubscribe
unsubscribe: function (observerToRemove) {
this.observers = this.observers.filter(observer => {
return observer !== observerToRemove;
})
},
// Events trigger
fire: function () {
this.observers.forEach(observer => {
observer.call();
});
}
}

Verify that the subscription was successful :

 subject = new Subject();
function observer1() {
console.log('Observer 1 Firing!');
}
function observer2() {
console.log('Observer 2 Firing!');
}
subject.subscribe(observer1);
subject.subscribe(observer2);
subject.fire();
// Output :
Observer 1 Firing!
Observer 2 Firing!

Verify that unsubscribe was successful :

subject.unsubscribe(observer2);
subject.fire();
Observer 1 Firing!

scene

  • DOM event
.body.addEventListener('click', function() {
console.log('hello world!');
});
document.body.click()
  • vue Response type

advantage

  • Support simple broadcast communication , Automatically notify all subscribed objects
  • The abstract coupling relationship between the target object and the observer can be extended and reused separately
  • Increased flexibility
  • What the observer pattern does is decouple , Make both sides of the coupling dependent on abstraction , Rather than depending on the concrete . So that their changes will not affect the changes on the other side .

shortcoming

  • Overuse can weaken the relationship between objects , It will make the program difficult to track, maintain and understand

8. Intermediary model (Mediator Pattern)

In the mediator model , Intermediary (Mediator) It encapsulates a series of ways in which objects interact , So that these objects don't have to interact directly , It's about mediators coordinating their interactions , So that they can be loosely coupled . When the action between certain objects changes , Does not immediately affect the role of some other objects , Make sure that these functions can be changed independently of each other .

There are some similarities between the mediator model and the observer model , It's all one to many relationships , It's all centralized communication , The difference is that the mediator pattern deals with interactions between peers , And the observer model is processing Observer and Subject Interaction between . The intermediary model is somewhat like a marriage intermediary , The blind date can't communicate directly at first , It's about screening matches through intermediaries and deciding who to meet with .

scene

  • For example, shopping cart demand , There is a product selection form 、 Color selection form 、 Purchase quantity form and so on , Will trigger change event , Then you can forward and process these events through the mediator , Decouple the events , Just maintain the mediator object .
 goods = { // Mobile phone inventory
'red|32G': 3,
'red|64G': 1,
'blue|32G': 7,
'blue|32G': 6,
};
// Intermediary
var mediator = (function() {
var colorSelect = document.getElementById('colorSelect');
var memorySelect = document.getElementById('memorySelect');
var numSelect = document.getElementById('numSelect');
return {
changed: function(obj) {
switch(obj){
case colorSelect:
//TODO
break;
case memorySelect:
//TODO
break;
case numSelect:
//TODO
break;
}
}
}
})();
colorSelect.onchange = function() {
mediator.changed(this);
};
memorySelect.onchange = function() {
mediator.changed(this);
};
numSelect.onchange = function() {
mediator.changed(this);
};
  • In the chat room

Member class chat room :

{
this.name = name;
this.chatroom = null;
}
Member.prototype = {
// Send a message
send: function (message, toMember) {
this.chatroom.send(message, this, toMember);
},
// receive messages
receive: function (message, fromMember) {
console.log(`${fromMember.name} to ${this.name}: ${message}`);
}
}

Chat room class :

{
this.members = {};
}
Chatroom.prototype = {
// Add members
addMember: function (member) {
this.members[member.name] = member;
member.chatroom = this;
},
// Send a message
send: function (message, fromMember, toMember) {
toMember.receive(message, fromMember);
}
}

Test it :

 chatroom = new Chatroom();
const bruce = new Member('bruce');
const frank = new Member('frank');
chatroom.addMember(bruce);
chatroom.addMember(frank);
bruce.send('Hey frank', frank);
// Output :bruce to frank: hello frank

advantage

  • Loose coupling between objects , And they can change their interaction independently
  • The one to many relationship between the mediator and the object replaces the mesh many to many relationship between the objects
  • If the complex coupling between objects makes maintenance difficult , And the coupling increases rapidly with the change of the project , You need the mediator to refactor the code

shortcoming

  • A mediator object will be added to the system , Because of the complexity of the interaction between objects , The complexity of transitioning to an intermediary object , Make the intermediary object often huge . The mediation The object itself is often a difficult object to maintain .

9. Visitor mode (Visitor Pattern)

Visitor mode It is a design pattern that separates algorithm from object structure , In layman's terms : Visitor mode allows us to add new logic to an object without changing its structure , The added logic is stored in a separate visitor object . Visitor patterns are often used to expand third-party libraries and tools .

class Visitor {
constructor() {}
visitConcreteElement(ConcreteElement) {
ConcreteElement.operation()
}
}
// Element class
class ConcreteElement{
constructor() {
}
operation() {
console.log("ConcreteElement.operation invoked");
}
accept(visitor) {
visitor.visitConcreteElement(this)
}
}
// client
let visitor = new Visitor()
let element = new ConcreteElement()
elementA.accept(visitor)

The implementation of the visitor pattern has the following elements :

  • Visitor Object: Visitor object , To have a visit() Method
  • Receiving Object: The recipient , To have a accept() Method
  • visit(receivingObj): be used for Visitor Receive one Receiving Object
  • accept(visitor): be used for Receving Object Receive one Visitor, And by calling Visitor Of visit() Provide access to Receiving Object The power of data

The simple code implementation is as follows :

Receiving :
function Employee(name, salary) {
this.name = name;
this.salary = salary;
}
Employee.prototype = {
getSalary: function () {
return this.salary;
},
setSalary: function (salary) {
this.salary = salary;
},
accept: function (visitor) {
visitor.visit(this);
}
}
Visitor Object:
function Visitor() { }
Visitor.prototype = {
visit: function (employee) {
employee.setSalary(employee.getSalary() * 2);
}
}

Check it out :

 employee = new Employee('bruce', 1000);
const visitor = new Visitor();
employee.accept(visitor);
console.log(employee.getSalary());// Output :2000

scene

  • The classes corresponding to the objects in the object structure rarely change , But it is often necessary to define new operations on this object structure
  • There are many different and unrelated operations on objects in an object structure , We need to avoid these operations " Pollution " Classes for these objects , You also do not want to modify these classes when adding new operations .

advantage

  • Comply with the single responsibility principle
  • Excellent scalability
  • flexibility

shortcoming

  • Specific elements to visitors to publish details , In violation of Dimitar's principle
  • Violation of the principle of Dependence Inversion , Dependent on concrete class , No dependency on abstraction .
  • It's difficult to change specific elements

The latter

above 66 This article is the summary of the recent resumption , On the whole, it's in the order from shallow to deep , A small part of the content is not original , I've posted a link at the end of each reference , Here, I would like to thank you for your blogs , It helped me a lot ~

The front end is a hodgepodge , Various frameworks emerge in endlessly , But everything changes JS, Pragmatic basis is fundamental , If you think this article will help you , Please give me a favor ~

This article is from WeChat official account. - The sea, here I come (bubuzouweb) , author :Jake Zhang

The source and reprint of the original text are detailed in the text , If there is any infringement , Please contact the [email protected] Delete .

Original publication time : 2021-02-05

Participation of this paper Tencent cloud media sharing plan , You are welcome to join us , share .

版权声明
本文为[User 4456933]所创,转载请带上原文链接,感谢
https://qdmana.com/2021/06/20210601154031600e.html

  1. HTML + CSS + JavaScript to achieve cool Fireworks (cloud like particle text 3D opening)
  2. HTML + CSS + JavaScript realizes 520 advertising love tree (including music), which is necessary for programmers to express themselves
  3. Solve the problem of Web front-end deployment server (it can be deployed online without a server)
  4. HTML + CSS + JS make wedding countdown web page template (520 / Tanabata Valentine's Day / programmer advertisement)
  5. What else can driverless minibus do besides "Park connection"?
  6. Cloud native leads the era of all cloud development
  7. NRM mirror source management tool
  8. Bring it to you, flex Jiugong
  9. Lolstyle UI component development practice (II) -- button group component
  10. Deconstruction assignment in ES6
  11. Luo 2 peerless Tang clan was officially launched. The official gave a key point, and the broadcast time was implied
  12. 20初识前端HTML(1)
  13. 当新零售遇上 Serverless
  14. 20 initial knowledge of front-end HTML (1)
  15. When new retail meets serverless
  16. [golang] - go into go language lesson 5 type conversion
  17. [golang] - go into go language lesson 6 conditional expression
  18. HTML5(八)——SVG 之 path 详解
  19. HTML5 (8) -- detailed explanation of SVG path
  20. 需要开通VIP以后页面内容才能复制怎么办?控制台禁用javascript即可
  21. Web前端|CSS入门教程(超详细的CSS使用讲解,适合前端初学者)
  22. 实践积累 —— 用Vue3简单写一个单行横向滚动组件
  23. Serverless 全能选手,再下一城
  24. What if you need to open a VIP to copy the page content? Just disable JavaScript on the console
  25. Web front end | CSS introductory tutorial (super detailed CSS explanation, suitable for front-end beginners)
  26. Practice accumulation - write a single line horizontal scroll component simply with vue3
  27. Dili Reba is thin again. She looks elegant and high in a strapless hollow skirt, and her "palm waist" is beautiful to a new height
  28. Serverless all-round player, next city
  29. The difference between MySQL semi synchronous replication and lossless semi synchronous replication
  30. Vue表单设计器的终极解决方案
  31. The ultimate solution for Vue form designer
  32. Nginx从理论到实践超详细笔记
  33. Yu Shuxin's red backless swimsuit is split to the waist and tail, with a concave convex figure and excessive color matching, and his face is white to dazzling
  34. Nginx ultra detailed notes from theory to practice
  35. 【动画消消乐|CSS】086.炫酷水波浪Loading过渡动画
  36. typecho全站启用https
  37. CCTV has another popular employee. The off-site interpretation is very professional, and the appearance ability is no less than that of Wang Bingbing
  38. [animation Xiaole | CSS] 086. Cool water wave loading transition animation
  39. Enable HTTPS in Typecho
  40. 50天用JavaScript完成50个web项目,我学到了什么?
  41. 根据JavaScript中原生的XMLHttpRequest实现jQuery的Ajax
  42. What have I learned from completing 50 web projects with JavaScript in 50 days?
  43. "My neighbor doesn't grow up" has hit the whole network. There are countless horse music circles, and actor Zhou Xiaochuan has successfully made a circle
  44. 根据JavaScript中原生的XMLHttpRequest实现jQuery的Ajax
  45. Implement the Ajax of jQuery according to the native XMLHttpRequest in JavaScript
  46. Implement the Ajax of jQuery according to the native XMLHttpRequest in JavaScript
  47. 30 + women still wear less T-shirts and jeans. If they wear them like stars, they will lose weight
  48. 数栈技术分享前端篇:TS,看你哪里逃~
  49. Several stack technology sharing front end: TS, see where you escape~
  50. 舍弃Kong和Nginx,Apache APISIX 在趣链科技 BaaS 平台的落地实践
  51. Abandon the landing practice of Kong and nginx, Apache apisik on the baas platform of fun chain technology
  52. 浪迹天涯king教你用elementui做复杂的表格,去处理报表数据(合并表头,合并表体行和列)
  53. 前端HTML两万字图文大总结,快来看看你会多少!【️熬夜整理&建议收藏️】
  54. Wandering around the world king teaches you to use elementui to make complex tables and process report data (merge header, merge table body rows and columns)
  55. 路由刷新数据丢失 - vuex数据读取的问题
  56. Front end HTML 20000 word graphic summary, come and see how much you can【 Stay up late to sort out & suggestions]
  57. Route refresh data loss - vuex data reading problem
  58. Systemctl系统启动Nginx服务脚本
  59. Systemctl system startup nginx service script
  60. sleepless