In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article introduces 66 JavaScript interview knowledge points and answer analysis, the content is very detailed, interested friends can refer to, hope to be helpful to you.
Today's topic is 66 JavaScript knowledge points written in the title.
HTML&CSS:
Browser kernel
Box model, flex layout, 2 / 3 column layout, horizontal / vertical center
BFC, clear float
Css3 animation, H5 new features.
JavaScript:
Inheritance, prototype chain, this pointing, Design pattern, call, apply, bind
New implementation, anti-jitter throttling, let, var, const distinction, temporary dead zone, event, loop
Promise usage and implementation, promise parallel execution and sequential execution
Advantages and disadvantages of async/await
Closures, garbage collection and memory leaks, array methods, array disorder, array flattening, event delegation, event listening, event model
Vue:
Principle of two-way binding of vue data
Vue computed principle, the difference between computed and watch
Vue compiler structure diagram, life cycle, vue component communication
Mvvm mode, mvc mode understanding
Vue dom diff 、 vuex 、 vue-router
Network:
HTTP1, HTTP2, HTTPS, common http status codes
Browse what happened from entering the URL to entering enter
Front-end security (CSRF, XSS)
Frontend cross-domain, browser cache, cookie, session, token, localstorage, sessionstorage
TCP connection (3-way handshake, 4-wave)
Performance dependent
The way of picture optimization
500 pictures, how to realize preloading optimization
Implementation of lazy loading
Ways to reduce http requests
In addition, I am also sorting out a more comprehensive set of interview questions. Let me first give you a preview picture:
Let's get to the point:
1. Introduce the data types of js and how the values are stored.
2. & &, | | and! What can operators do respectively
3. Data type conversion of js
4. Judgment of data type in JS (typeof,instanceof,constructor,Object.prototype.toString.call ())
5. What are the built-in objects in js?
6. What is the difference between undefined and undeclared?
7. What's the difference between null and undefined?
8. What are the results of valueOf and toString of {} and []?
9. The scope and chain of scope of Javascript?
10. How many ways does javascript create objects?
11. How many ways to implement JavaScript inheritance?
twelve。 The implementation of parasitic combinatorial inheritance?
13. Talk about your understanding of this, call, apply and bind
14. JavaScript prototype, prototype chain? What are the characteristics?
15. How does js get the prototype?
16. What is a closure and why use it?
17. What are DOM and BOM?
18. What are the three event models?
19. What is the event delegate?
20. What is event propagation?
21. What is event capture?
twenty-two。 What is event bubbling?
23. DOM operations-how do I add, remove, move, copy, create, and find nodes?
24. List the native methods of js arrays and objects
25. Common regular expressions
twenty-six。 What is Ajax? How do I create an Ajax?
twenty-seven。 What are the ways to delay loading of js?
twenty-eight。 Tell me about your understanding of modular development?
twenty-nine。 How many module specifications of js?
thirty。 What is the difference between AMD and CMD specifications?
thirty-one。 The difference between ES6 module and CommonJS module, AMD, CMD.
thirty-two。 What is the core principle of requireJS?
thirty-three。 Talking about the Operation Mechanism of JS
thirty-four。 What is the object of arguments?
thirty-five。 Why does `b` in the code become a global variable when calling this function?
thirty-six。 A brief introduction to the garbage collection mechanism of V8 engine
thirty-seven。 What actions can cause memory leaks?
thirty-eight。 What is ECMAScript?
thirty-nine。 What are the new features of ECMAScript 2015 (ES6)?
forty。 What is the difference between `var`, `let` and `var`?
forty-one。 What is the arrowhead function?
forty-two。 What is a class?
forty-three。 What is a template string?
forty-four。 What is object deconstruction?
45 what is the `Set` object and how does it work?
forty-six。 What is Proxy?
-
High-energy early warning split line ⚡-
forty-seven。 Write a general event listener function, why use it?
forty-eight。 What is functional programming? What are the features of JavaScript that make it a candidate for functional languages?
forty-nine。 What is a higher-order function?
fifty。 Why are functions called first-class citizens?
fifty-one。 Manually implement `Array.prototype.map method `
fifty-two。 Manually implement the `Array.prototype.filter` method
fifty-three。 Manually implement the `Array.prototype.reduce` method
fifty-four。 Deep and shallow copy of js
fifty-five。 Handwritten call, apply and bind functions
fifty-six。 The realization of Corialization of function
fifty-seven。 Implementation of js Simulation new operator
fifty-eight。 What is a callback function? What are the disadvantages of callback function
fifty-nine。 What is Promise? can you implement it by hand?
sixty。 What is `Iterator` and what is its function?
sixty-one。 What is the `Generator` function and what is its function?
sixty-two。 What is `async/ Await` and how it works, and what are its advantages and disadvantages?
sixty-three。 What is the principle of instanceof and how to implement it?
sixty-four。 Throttling and Anti-shaking of js
sixty-five。 What is a design pattern?
sixty-six。 9 common front-end design patterns
1. Introduce the data types of js and how the values are stored.
For details, please see my previous article: "Front end package" is probably the most thorough explanation of JavaScript data types.
JavaScript has a total of 8 data types, of which there are 7 basic data types: Undefined, Null, Boolean, Number, String, Symbol (new to es6 for unique values) and BigInt (new to es10)
A reference data type, Object (Object is essentially made up of an unordered set of name-value pairs). It contains function, Array, Date and so on. JavaScript does not support any mechanism for creating custom types, and all values will eventually be one of the above eight data types.
Original data type: directly stored in the stack (stack), occupies a small space, the size is fixed, belongs to the frequently used data, so put into the stack storage.
Reference data type: it is stored in both stack and heap, occupying a lot of space and not fixed in size. The reference data type stores a pointer in the stack to the starting address of the entity in the heap. When the interpreter looks for a reference value, it first retrieves its address in the stack, obtains the address and then obtains the entity from the heap.
2. & &, | | and! What can operators do respectively
The & & called logical and finds the first imaginary expression in its Operand and returns it, and if no virtual expression is found, the last truth expression is returned. It uses a short circuit to prevent unnecessary work.
| | logical OR. Find the first truth expression in its Operand and return it. | This also uses a short circuit to prevent unnecessary work. Before the ES6 default function parameter is supported, it is used to initialize the default parameter value in the function.
!! Operator can cast the value on the right to a Boolean value, which is an easy way to convert a value to a Boolean value.
3. Data type conversion of js
There are only three cases of type conversion in JS, which are:
Convert to a Boolean (call the Boolean () method)
Convert to numbers (call Number (), parseInt (), and parseFloat () methods)
Convert to a string (call .toString () or String () method)
Null and underfined do not have .toString method
In addition, there are some operators that have implicit conversion. If you do not expand here, you can use Baidu 00.
4. Judgment of data type in JS (typeof,instanceof,constructor,Object.prototype.toString.call ())
(1) typeof
Typeof for primitive types, except for null, can display the correct type
Console.log (typeof 2); / / number console.log (typeof true); / / boolean console.log (typeof 'str'); / / string console.log (typeof []); / / the data type of the object [] array is interpreted in typeof as object console.log (typeof function () {}); / / function console.log (typeof {}) / / object console.log (typeof undefined); / / undefined console.log (typeof null); / / the data type of object null is interpreted as object by typeof
Typeof for objects, except functions will display object, so typeof can not accurately determine what type of variable is, so if you want to determine the correct type of an object, you can consider using instanceof
(2) instanceof
Instanceof can correctly determine the type of object, because the internal mechanism is to determine whether the type prototype can be found in the prototype chain of the object.
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)
It can be seen that the literal value determines the data type directly, and instanceof can accurately judge the reference data type (Array,Function,Object), while the basic data type can not be accurately judged by instanceof.
Let's take a look at the explanation of instanceof in MDN: the instanceof operator is used to test whether an object has a prototype property of a constructor in its prototype chain. It means to determine whether an object is an instance of a data type, such as Array, and focus on determining whether an object is an instance of a data type. Here the literal value, 2, true, 'str' is not an 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 is a pit here. If I create an object and change its prototype, constructor 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 the prototype method toString of the Object object, use call to change the prince of the raccoon, and borrow the toString method of Object
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. What are the built-in objects in js?
Knowledge points involved:
Global objects (global objects), or standard built-in objects, should not be confused with "global objects (global object)". The global object here refers to the object in the global scope. Other objects in the global scope can be created by the user's script or provided by the host program. Standard built-in object classification (1) value attributes, these global properties return a simple value, these values do not have their own properties and methods. For example, Infinity, NaN, undefined, null literal (2) function attributes, the global function can be called directly, there is no need to specify the object to which it belongs, and the result will be returned directly to the caller after execution. For example, eval (), parseFloat (), parseInt (), etc. (3) basic objects, which 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) numeric and date objects that represent numbers, dates, and objects that perform mathematical calculations. For example, the Number, Math, Date (5) strings are used to represent and manipulate the objects of the string. For example, String, RegExp (6) indexable collection objects that represent collections of data sorted by index values, including arrays and type arrays, as well as objects with class array structures. For example, Array (7) uses key collection objects that use keys when storing data and support iterating elements in the order in which they are inserted. For example, Map, Set, WeakMap, WeakSet (8) vector set, the data in the SIMD vector set is organized into a data sequence. For example, SIMD et al. (9) structured data, these objects are used to represent and manipulate structured buffer data, or data encoded by JSON. For example, JSON and the like (10) control abstract objects such as Promise, Generator, etc. (11) reflect objects such as Reflect, Proxy (12) internationalization, and add ECMAScript objects to support multilingual processing. For example, Intl, Intl.Collator, etc. (13) WebAssembly (14) others such as arguments
The built-in object in js mainly refers to the js that exists in the global scope before the program is executed.
Some defined global value properties, functions, and constructors used to instantiate other objects
Count objects. In general, we often use global variable values such as NaN and undefined, and global functions such as parseInt () and parseFloat () to instantiate the construction of objects.
Building functions such as Date, Object, etc., as well as single built-in objects such as Math objects that provide mathematical calculations.
For more information, please refer to:
Classification of Standard built-in objects
"Summary of all JS built-in object properties and methods"
6. What is the difference between undefined and undeclared?
Variables that have been declared in scope but have not yet been assigned are undefined. In contrast, variables that have not yet been declared in scope are undeclared.
For references to undeclared variables, the browser reports a reference error, such as ReferenceError: b is not defined. But we can use typ
Eof's security mechanism to avoid error reporting, because for undeclared (or not defined) variables, typeof returns "undefined".
7. What's the difference between null and undefined?
First of all, Undefined and Null are both basic data types, and each of these basic data types has only one value, undefined and null.
The meaning of undefined stands for undefined
Null stands for empty object. Undefined,null is returned when a general variable is declared but not yet defined.
It is mainly used to assign values to variables that may return objects as initialization.
Undefined is not a reserved word in js, which means that we can use undefined as a variable name, which is very dangerous.
It will affect our judgment of undefined value. But there are some ways to get a safe undefined value, such as void 0.
When we use typeof to judge two types, Null typing returns "object", which is a legacy of history. When we use double class
Returns true when comparing two types of values, and false when three equal signs are used.
For more information, please refer to:
"undefined and null deeply understood by JavaScript"
8. What are the results of valueOf and toString of {} and []?
The valueOf result of {} is {}, the result of toString is "[object Object]" [], the valueOf result is [], the result of toString is ""
9. Scope and chain of scope of Javascript
Scope: a scope is the area that defines variables and has a set of rules for accessing variables that govern how the browser engine looks up variables (identifiers) based on variables in the current scope as well as in nested scopes.
Scope chain: the function of the scope chain is to ensure orderly access to all variables and functions that the execution environment has access to. Through the scope chain, we can access variables and functions of the outer environment.
Function.
The scope chain is essentially a list of pointers to variable objects. A variable object is an object that contains all variables and functions in the execution environment. The front of the domain chain
The side is always the variable object of the current execution context. The variable object of the global execution context (that is, the global object) is always the last object in the scope chain.
When we look for a variable, if it is not found in the current execution environment, we can look back along the scope chain.
The process of creating a scope chain is related to the establishment of the execution context. .
For more information, please refer to:
"JavaScript's in-depth understanding of the scope chain"
You can also take a look at my article: "Front-end package" delves into JavaScript scope (chain) knowledge points and closures
10. How many ways does javascript create objects?
We usually create objects directly in the form of literals, but this way of creation produces a lot of repetitive code when creating a large number of similar objects. But js is different from a general object-oriented language in that it didn't have the concept of classes before ES6. But we can use functions to simulate, resulting in reusable object creation. I have learned that there are several ways: (1) the first is the factory mode, the main working principle of the factory pattern is to use functions to encapsulate the details of creating objects, so as to achieve the purpose of reuse by calling functions. But it has a big problem is that the created object can not be associated with a type, it simply encapsulates the reuse code, but does not establish the relationship between the object and the type. (2) the second is the constructor model. Every function in js can be used as a constructor, as long as a function is called through new, then we can call it a constructor. Executing the constructor first creates an object, then points the prototype of the object to the constructor's prototype property, then points the this in the execution context to the object, and finally executes the entire function, and returns the newly created object if the return value is not the object. Because the value of this points to the newly created object, we can use this to assign values to the object. The advantage of the constructor pattern over the factory pattern is that the object created is related to the constructor, so we can identify the type of the object through the prototype. But a disadvantage of the constructor is that it results in unnecessary creation of the function object, because the function is also an object in js, so if the object property contains a function, then every time we will create a new function object, wasting unnecessary memory space, because the function is universal for all instances. (3) the third mode is the prototype mode, because each function has a prototype property, which is an object that contains properties and methods that can be shared by all instances created through the constructor. So we can use prototype objects to add common properties and methods to achieve code reuse. Compared with the constructor mode, this method solves the problem of reuse of function objects. But there are some problems with this mode, one is that there is no way to initialize the value by passing in parameters, and the other is that if there is a value of a reference type such as Array, then all instances will share an object, and the change of one instance to the value of the reference type will affect all instances. (4) the fourth pattern is a combination of constructor pattern and prototype pattern, which is the most common way to create custom types. Because there are some problems in the separate use of constructor pattern and prototype pattern, we can combine these two patterns to initialize the properties of objects through constructors and reuse function methods through prototype objects. This method solves the disadvantage of using the two modes alone, but one deficiency is that the encapsulation of the code is not good enough because of the use of two different modes. (5) the fifth mode is the dynamic prototype mode, which moves the creation process of the prototype method assignment to the interior of the constructor by judging whether the attribute exists or not. the effect of assigning a value to the prototype object only once when the function is called for the first time can be achieved. This approach encapsulates the above hybrid mode very well. (6) the sixth pattern is the parasitic constructor pattern, which is basically the same as the factory pattern. My understanding of this pattern is that it is mainly based on an existing type and extends the instantiated object when instantiating. In this way, there is no need to modify the original constructor, but also to achieve the purpose of extending the object. One of its disadvantages, like the factory pattern, is that it cannot identify objects. Well, that's all I've learned so far.
For more information, please refer to:
"object creation with in-depth understanding of JavaScript"
11. How many ways to implement JavaScript inheritance?
I know several ways to achieve inheritance in js: (1) the first is to achieve inheritance in the way of prototype chain, but the disadvantage of this implementation is that when it contains data of reference type, it will be shared by all instance objects, which is easy to cause confusion of modification. Also, you cannot pass parameters to the supertype when you create a subtype. (2) the second way is to borrow the constructor, which is realized by calling the supertype constructor in the function of the subtype, which solves the disadvantage that parameters can not be passed to the supertype. however, one of its problems is that it is unable to reuse function methods, and the method subtypes defined by supertype prototypes are not accessible. (3) the third way is combinatorial inheritance, which is a way of combining prototype chain and borrowing constructor. The property inheritance of the type is realized by borrowing the constructor, and the method inheritance is realized by setting the prototype of the subtype to the instance of the supertype. This approach solves the problem when the above two patterns are used separately, but because we use the instance of the supertype as the prototype of the subtype, we call the constructor of the superclass twice, resulting in a lot of unnecessary attributes in the prototype of the subtype. (4) the fourth way is prototype inheritance, the main idea of prototype inheritance is to create a new object based on the existing object, the principle of implementation is to pass an object into the function, and then return an object based on this object. The main purpose of this kind of inheritance is not to create a new type, but to implement a simple inheritance to an object. The Object.create () method defined in ES5 is the implementation of prototype inheritance. The disadvantage is 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, pass in an object, then copy a copy of the object, then extend the object, and finally return the object. This extension process can be understood as a kind of inheritance. The advantage of this inheritance is that it inherits a simple object if it is not our custom type. The disadvantage is that there is no way to reuse the function. (6) the sixth way is parasitic combinatorial inheritance. the disadvantage of combinatorial inheritance is that it uses the instance of supertype as the prototype of subtype, which leads to the addition of unnecessary prototype attributes. Parasitic combination inheritance is done by using a copy of the supertype prototype as the prototype of the subtype, thus avoiding the creation of unnecessary properties.
For more information, please refer to:
"inheritance of JavaScript's in-depth understanding"
twelve。 The implementation of parasitic combinatorial inheritance?
Function Person (name) {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); StudentStudent.prototype.constructor = Student Student.prototype.sayMyGrade = function () {console.log ("My grade is" + this.grade + ".");}
13. Talk about your understanding of this, call, apply and bind
For details, please see my previous article: "Front-end package" to thoroughly understand this, call, apply and bind in JavaScript.
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
In the browser, this points to the window object globally
In a function, this always points to the object that called him last.
In the constructor, this points to the new object that comes out of new
The this in call, apply, and bind is strongly bound to the specified object
This is special in the arrow function. The arrow function this is the this of the parent scope, not the this when called. You should know that the first four ways are determined when calling, that is, dynamic, while the this direction of the arrow function is static, which is determined when it is declared.
Apply, call, and bind are all built-in API to the function by js. Calling them can specify the execution of this for the function and pass parameters at the same time.
14. JavaScript prototype, prototype chain? What are the characteristics?
In js, we use constructors to create a new object. Inside each constructor, there is a prototype property value, which is a value of the
For example, this object contains properties and methods that can be shared by all instances of the constructor. When we use the constructor to create a new object, inside the object
It will contain a pointer to the value corresponding to the prototype property of the constructor, which in ES5 is called the prototype of the object. Generally speaking, we
Should not be able to get this value, but now browsers all implement the proto property to let us access this property, but we'd better not use this
Because it is not specified in the specification. A new Object.getPrototypeOf () method has been added to ES5, which can be used to obtain the
The prototype of the elephant.
When we access a property of an object, if the property does not exist inside the object, it will look for the property in its prototype object, which then
Will have their own prototype, so keep looking like this, that is, the concept of prototype chain. Generally speaking, the end of the prototype chain is Object.prototype, so this is
Is the reason why our newly created objects can use methods such as toString ().
Features:
JavaScript objects are passed by reference, and each new object entity we create does not have its own prototype copy. When we modify the prototype, it is associated with
The relevant objects will also inherit this change.
Reference article:
"prototype and prototype chain for JavaScript's in-depth understanding"
You can also take a look at what I wrote: "Front end package" with an in-depth understanding of JavaScript prototypes and prototype chains.
15. How does js get the prototype?
P.proto
P.constructor.prototype
Object.getPrototypeOf (p)
16. What is a closure and why use it?
A closure is a function that has access to variables in the scope of another function. The most common way to create a closure is to create another function within a function.
Accesses the local variable of the current function.
Closures have two common uses.
The first use of closures is to enable us to access variables inside the function outside the function. By using closures, we can access variables inside the function externally by calling the closure function externally, and we can use this method to create private variables.
Another use of the function is to keep the variable object in the context of the function that has been run out of memory, because the closure function retains a reference to the variable object, so the variable object is not recycled.
Function a () {var n = 0; function add () {nkeeper; console.log (n);} return add;} var aa1 = a (); / / Note that the function name is only an identification (a pointer to the function), and () is the executing function; A1 (); / / 1A1 (); / / 2 the second call n variable is still in memory.
In fact, the essence of closure is a special application of domain chain. As long as we understand the process of creating domain chain, we can understand the implementation principle of closure.
17. What are DOM and BOM?
DOM refers to the document object model, which refers to treating a document as an object, which mainly defines the methods and interfaces for dealing with web content.
BOM refers to the browser object model, which refers to treating the browser as an object, which mainly defines the methods and interfaces that interact with the browser. BOM
The core of window is window, while the window object has a dual role, which is not only an interface to access the browser window through js, but also a Global (global).
Object. This means that any objects, variables, and functions defined in a web page exist as a property or method of a global object. The window object contains locati
On object, navigator object, screen object and other sub-objects, and the most fundamental object of DOM, document object, is also the window pair of BOM.
The child of the elephant.
Related information:
"what's the difference between DOM, DOCUMENT, BOM, WINDOW?"
"Window object"
"what are DOM and BOM, respectively, and what is the relationship? "
Summary of JavaScript Learning (3) detailed explanation of BOM and DOM
18. What are the three event models?
Events are the interactive actions that occur when the user operates the web page or some actions of the web page itself. There are three event models in modern browsers.
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
DOM0-level model: this model does not propagate, so there is no concept of event flow, but now some browsers support bubbling, which can define listening functions directly in web pages or specify listening functions through the js property. This approach is compatible with all browsers.
2. IE event model: in this event model, there are two processes for an event, the event processing phase and the event bubbling phase. The event handling phase first executes the listening event bound to the target element. Then there is the event bubbling phase, which refers to the event bubbling from the target element to the document, checking whether the passing node is bound to the event listener function, and if so, executing it. This model adds listening functions through attachEvent, and multiple listening functions can be added, which will be executed sequentially.
3. DOM2 level event model: in this event model, there are three processes for an event, and the first process is the event capture phase. Capture means that the event propagates all the way down from the document to the target element, checking in turn whether the passing node is bound to the event listener function, and if so, executing it. The latter two phases are the same as the two phases of the IE event model. In this event model, the event binding function is addEventListener, where the third parameter specifies whether the event is executed during the capture phase.
Related information:
"when a DOM element binds multiple events, perform bubbling or capture first"
19. What is the event delegate?
Event delegation essentially takes advantage of the bubbling mechanism of browser events. Because the event is passed to the parent node during bubbling, and the parent node can get it through the event object
The target node, so the listening function of the child node can be defined on the parent node, and the listening function of the parent node uniformly handles the events of multiple child elements, which is called event agent.
With event proxies, it is not necessary to bind a listening event for each child element, thus reducing memory consumption. And using the event broker, we can also achieve the dynamic binding of events, such as adding a new child node, we do not need to add a listening event for it separately, the events it occurs will be handed over to the listener function in the parent element to deal with.
Related information:
"detailed explanation of JavaScript event delegation"
20. What is event propagation?
When an event occurs on a DOM element, the event does not happen exactly on that element. In "when the event occurs on the DOM element, the event does not happen exactly on that element. In the" bubbling phase ", the event bubbles or propagates up to the parent, grandparent, or parent until it reaches the window; in the" capture phase ", the event triggers the element event or event.target down from the window.
There are three stages of event propagation: "in, the event bubbles or propagates up to the parent, grandparent, or parent until it reaches the window, while in the" capture phase ", the event triggers the element event or event.target down from the window.
There are three stages of event propagation:
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
Capture phase-the event starts at window and then goes down to each element until it reaches the target element.
Target phase-the event has reached the target element.
Bubbling phase-the event bubbles from the target element and then rises to each element until it reaches the window.
21. What is event capture?
When an event occurs on a DOM element, the event does not happen exactly on that element. In the capture phase, the event starts at window and goes all the way to the element that triggers the event. Window---- > document---- > html---- > body-> Target element
Suppose you have the following HTML structure:
one
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');})})
The addEventListener method has a third optional parameter, useCapture, whose default value is false, and the event will occur during the bubbling phase or, if true, during the capture phase. If you click the child element, it will print window,document,html,grandparent and parent on the console, respectively, which is called event capture.
twenty-two。 What is event bubbling?
Event bubbling is the opposite of event capture, the current element-> body-> html---- > document-> window. When an event occurs on a DOM element, the event does not happen exactly on that element. In the bubbling phase, the event bubbles, or the event occurs in its parents, grandparents, grandparents, until it reaches window.
Suppose you have the following HTML structure:
one
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');})})
The addEventListener method has a third optional parameter, useCapture, whose default value is false, and the event will occur during the bubbling phase or, if true, during the capture phase. If you click the child element, it will print child,parent,grandparent,html,document and window on the console, respectively, which is the event bubbling.
23. DOM operations-how do I add, remove, move, copy, create, and find nodes?
(1) create a new node
CreateDocumentFragment () / / create a DOM fragment createElement () / / create a specific element createTextNode () / / create a text node
(2) add, remove, replace, insert
AppendChild (node) removeChild (node) replaceChild (new,old) insertBefore (new,old)
(3) find
GetElementById (); getElementsByName (); getElementsByTagName (); getElementsByClassName (); querySelector (); querySelectorAll ()
(4) attribute operation
GetAttribute (key); setAttribute (key, value); hasAttribute (key); removeAttribute (key)
Related information:
Overview of DOM
"Summary of DOM operations for native JavaScript"
"DOM node-related API collections in native JS"
24. List the native methods of js arrays and objects
25. Common regular expressions
/ / (1) match hexadecimal color values var color = / # ([0-9a-fA-F] {6} | [0-9a-fA-F] {3}) / g; / / (2) match dates, 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) match qq number var qq = / ^ [1-9] [0-9] {4 a-zA-Z0 10} $/ g; / / (4) Mobile phone number regular var phone = / ^ 1 [34578]\ d {9} $/ g; / / (5) user name regular var username = / ^ [a-zA-Z\ $] [a-zA-Z0-9\ $] {4c16} $/ / / (6) Email regular var email = / ^ ([A-Za-z0-9 _\ -\.]) + @ ([A-Za-z0-9 _\ -\.]) +\. ([A-Za-z] {2jue 4}) $/ / / (7) ID card number (18 digits) 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 murz\.] {2Magi 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) / / license plate number regular var cPattern = / ^ [Beijing, Tianjin, Shanghai, Chongqing, Hebei, Henan, Yunnan, Liao Black, Hunan, Anhui, New Jiangsu, Zhejiang, Jiangxi, Hubei, Guangxi, Ganjin, Shaanxi, Ji, Fujian, Gui, Guangdong, Qinghai, Tibet, Sichuan and Ningqiong] {1} [A-Z0 Z] {1} [A-Z0-9] {4} [A-Z0-9 student police, Hong Kong and Macao] {1} $/ / / (11) strong password (must contain a combination of uppercase and lowercase letters and numbers, cannot use special characters, length is between 8 and 10): var pwd = / ^ (? =.\ d) (? =. [Amurz]) (? =. [Amurz]). {8J 10} $/
twenty-six。 What is Ajax? How do I create an Ajax?
My understanding of ajax is that it is an asynchronous communication method, by initiating http communication directly from the js script to the server, and then updating the corresponding part of the web page based on the data returned by the server, without refreshing the entire page.
Create steps:
Interview handwritten (native):
/ / 1: create Ajax object var xhr = window.XMLHttpRequest?new XMLHttpRequest (): new ActiveXObject ('Microsoft.XMLHTTP'); / / compatible with IE6 and the following versions / / 2: configure Ajax request address xhr.open (' get','index.xml',true); / / 3: send request xhr.send (null) / / rigorous writing / / 4: listen to requests and accept responses xhr.onreadysatechange=function () {if (xhr.readySates==4&&xhr.status==200 | | xhr.status==304) console.log (xhr.responsetXML)}
JQuery writing method
$.ajax ({type:'post', url:'', async:ture,//async Asynchronous sync synchronous data:data,// requests dataType:'jsonp', success:function (msg) {}, error:function (error) {}} for post)
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 http request xhr.open ("GET", url, true); / / set the state listening function xhr.onreadystatechange = function () {if (this.readyState! = = 4) return / / change the status of promise if (this.status = 200) {resolve (this.response);} else {reject (new Error (this.statusText));}}; / / set the 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 http request xhr.send (null);}); return promise;}
twenty-seven。 What are the ways to delay loading of js?
The loading, parsing and execution of js will block the rendering process of the page, so we hope that the js script can delay loading as much as possible and improve the rendering speed of the page.
Several ways I have learned are:
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
Place the js script at the bottom of the document to make the js script load and execute at the end as much as possible.
Add a defer attribute to the js script, which synchronizes the loading of the script with the parsing of the document, and then executes the script file after the parsing of the document is complete, so that the rendering of the page is not blocked. Multiple scripts with the defer property set end up being executed sequentially by specification, but this may not be the case in some browsers.
3. Add an async attribute to the js script, which causes the script to load asynchronously and does not block the parsing of the page, but executes the js script immediately after the script is loaded, which will also block if the document is not parsed. Scripts with multiple async attributes are executed in an unpredictable order and are generally not executed in the order of the code.
4. In the way of dynamically creating DOM tags, we can listen to the loading events of the document, and then dynamically create script tags to introduce js scripts when the document is loaded.
Related information:
"several ways of delayed loading of JS"
"HTML 5 async Properties"
twenty-eight。 Tell me about your understanding of modular development?
My understanding of a module is that a module is a set of methods that implement a particular function. In the beginning, js only implemented some simple functions, so there was no concept of module.
But as the program becomes more and more complex, the modular development of code becomes more and more important
Because the function has the characteristic of independent scope, the most original way of writing is to use the function as a module and several functions as a module, but this way is easy to cause pollution of global variables.
Dye, and there is no connection between modules.
Later, the object writing method is proposed, which is realized by using the function as an object, which solves some shortcomings of using the function as a module directly, but this method will expose the
There are all module members, and external code can modify the value of internal properties.
Now the most commonly used is to execute the function immediately, through the use of closures to achieve the establishment of the private scope of the module, while not polluting the global scope.
Related information:
"talking about Modular Development"
Javascript Modular programming (1): the Writing of Modules
"Front end Modularization: CommonJS,AMD,CMD,ES6"
The Grammar of Module
twenty-nine。 How many module specifications of js?
There are four module loading schemes that are more mature in js:
The first is the CommonJS scheme, which introduces the module through require and defines the output interface of the module through module.exports. This module loading scheme is a server-side solution, it introduces the module synchronously, because the files on the server are stored on the local disk, so it is very fast to read, so there is no problem to load synchronously. However, if it is on the browser side, because the module is loaded using a network request, it is more appropriate to use asynchronous loading.
The second is the AMD scheme, which loads the module asynchronously. 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, and then execute the callback function after the loading is completed. Require.js implements the AMD specification.
The third is the CMD scheme, which and the AMD scheme are to solve the problem of asynchronous module loading. Sea.js implements the CMD specification. It differs from require.js in that the dependency is handled differently when the module is defined and when the dependent module is executed.
The fourth scheme is the scheme proposed by ES6, which uses the form of import and export to import and export modules. This scheme is different from the above three. Ref. 61.
thirty。 What is the difference between AMD and CMD specifications?
There are two main differences between them.
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
The first aspect is that dependencies are handled differently when modules are defined. AMD favors dependency prefix, declaring the module on which it depends when defining the module. CMD, on the other hand, advocates proximity dependence and require only when a module is used.
The second aspect is to deal with the timing of the execution of dependent modules differently. First of all, both AMD and CMD load modules asynchronously, but the difference is that
The execution time of the module, AMD directly executes the dependent module after the dependent module is loaded, and the execution order of the dependent module is not necessarily consistent with the order in which we write. And CMD
After the dependent module is loaded, it is not executed, it is just downloaded. After all the dependent modules are loaded, enter the callback function logic and encounter the require statement.
The corresponding modules are executed so that the execution order of the modules is consistent with the order in which we write.
/ / CMD define (function (require, exports, module) {var a = require (". / a"); a.doSomething (); / / omit 100 lines here var b = require (". / b"); / / dependency can be written nearest b.doSomething (); / /.}) / / AMD recommends define by default ([. / a ",". / b "], function (a, b) {/ / dependency must write a.doSomething () at the beginning; / / omit 100 lines of b.doSomething () here; / /.})
Related information:
"Front-end modularization, the difference between AMD and CMD"
thirty-one。 The difference between ES6 module and CommonJS module, AMD, CMD.
The 1.CommonJS module outputs a copy of the value, and the ES6 module outputs a reference to the value. The output of the CommonJS module is the value
That is, once a value is output, changes within the module will not affect the value The operation mechanism of ES6 module is different from that of CommonJS. When the JS engine analyzes the script statically, it encounters the module load command import and generates a read-only reference. Wait until the script is actually executed, and then according to this read-only reference, go to the loaded module to get the value.
The 2.CommonJS module is loaded at run time, and the ES6 module is the compile-time output interface. A CommonJS module is an object, that is, when you type, you load the entire module, generate an object, and then read the method from that object. This kind of loading is called "runtime loading". While the ES6 module is not an object, its external interface is only a static definition, which will be generated in the code static parsing phase.
thirty-two。 What is the core principle of requireJS?
The core principle of require.js is to introduce modules asynchronously by dynamically creating script scripts, and then listen to the load events of each script, and then call the callback function if each script is loaded.
For more information, please refer to:
"Analysis of the usage and principle of requireJS" https://github.com/HRFE/blog/issues/10
"what is the core principle of requireJS? "https://zhuanlan.zhihu.com/p/55039478
"requireJS principle Analysis"] https://www.jianshu.com/p/5a39535909e4
thirty-three。 Talking about the Operation Mechanism of JS
1. Js single thread
One of the major features of the JavaScript language is single-threading, that is, you can only do one thing at a time.
The single thread of JavaScript is related to its purpose. As a browser scripting language, the main purpose of JavaScript is to interact with users and to manipulate DOM. This determines that it can only be single-threaded, otherwise it will bring very complex synchronization problems. For example, suppose JavaScript has two threads at the same time, one thread adds content to a DOM node and the other thread deletes the node, which thread should the browser follow?
So, to avoid complexity, JavaScript has been single-threaded since its birth, which has become a core feature of the language and will not change in the future.
2. Js event loop
There are many tasks during the execution of js code, which are generally divided into two categories:
Synchronization task
Asynchronous task
When we open a website, the rendering process of the web page is a lot of synchronization tasks, such as the rendering of page skeletons and page elements. Resource-intensive and time-consuming tasks such as loading pictures and music are asynchronous tasks. We use a map to illustrate:
Let's explain this picture:
Synchronous and asynchronous tasks enter different execution "places", synchronously enter the main thread, asynchronously enter Event Table and register functions.
When the specified thing is done, Event Table moves this function into Event Queue.
If the task in the main thread is empty, it will go to Event Queue to read the corresponding function and enter the main thread for execution.
The above process is repeated over and over again, which is often called Event Loop (event cycle).
So when is the main thread execution stack empty? There is a monitoring process process in the js engine, which will constantly check whether the main thread execution stack is empty. Once it is empty, it will go to Event Queue to check if there are any functions waiting to be called.
This is the overall process of js running.
It should be noted that in addition to synchronous and asynchronous tasks, tasks can also be more subdivided into macrotask (macro tasks) and microtask (micro tasks), and js engines will give priority to micro tasks.
Micro tasks include callbacks to promise, process.nextTick in node, and MutationObserver to listen for Dom changes. Macro tasks include the execution of script scripts, setTimeout, setInterval, setImmediate and other scheduled events, as well as Icano operations, UI dyeing and so on.
How to answer in the interview?
Here is my personally recommended answer:
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
First of all, js runs in a single thread, and when the code is executed, the execution context of different functions is pressed into the execution stack to ensure the orderly execution of the code.
When executing synchronous code, if an asynchronous event is encountered, the js engine will not wait for the result to be returned, but will suspend the event and continue to execute other tasks in the stack
When the synchronous event is executed, the callback corresponding to the asynchronous event is added to another task queue that is different from the current execution stack to wait for execution.
The task queue can be divided into macro task alignment and micro task alignment. When the events in the current execution stack are finished, the js engine will first determine whether there are any tasks in the micro task queue, and if so, press the events at the head of the micro task queue into the stack for execution.
Judge the tasks in the macro task column after the micro task has been executed on the column.
Finally, you can use the following question to test the harvest:
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 to execute, encounters setTimeout, throws the callback function of setTimeout into the macro task queue, executes the new Promise immediately, outputs the callback function of 2 then into the micro-task queue, and then continues to execute. When it encounters process.nextTick, it also throws the callback function to the task queue, and then continues to execute, outputting 5. When all synchronous tasks are completed, see if there are any micro-tasks that can be executed. It is found that there are two micro-tasks: then function and nextTick. Which one should be executed first? The asynchronous task specified by process.nextTick always occurs before all asynchronous tasks, so first execute process.nextTick output 4 and then execute the then function output 3, and the first round of execution ends.
The second round: starting from the macro task queue, the setTimeout callback is found, and the output 1 is finished, so the result is 25431
Related information:
Browser event Loop Mechanism (event loop)
"detailed explanation of the Event Loop (event Loop) mechanism in JavaScript"
"what is Event Loop? "
"this time, thoroughly understand the implementation mechanism of JavaScript."
thirty-four。 What is the object of arguments?
An arguments object is a collection of parameter values passed in a function. It is an array-like object because it has a length property, and we can use the array index notation arguments [1] to access a single value, but it does not have built-in methods in the array, such as forEach, reduce, filter, and map.
We can use Array.prototype.slice to convert arguments objects into an array.
Function one () {return Array.prototype.slice.call (arguments);}
Note: there is no arguments object in the arrow function.
Function one () {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 the function four, it throws a ReferenceError: arguments is not defined error. Using the restsyntax, you can solve this problem.
Const four = (... args) = > args
This automatically places all parameter values in the array.
thirty-five。 Why does `b` in the code become a global variable when calling this function?
Function myFunc () {let a = b = 0;} myFunc ()
The reason is that the assignment operator evaluates from right to left. This means that when multiple assignment operators appear in an expression, they are evaluated from right to left. So the above code looks like this:
Function myFunc () {let a = (b = 0);} myFunc ()
First, the expression b = 0 is evaluated, in this case b is not declared. Therefore, the JS engine creates a global variable b outside this function, and the expression b = 0 returns a value of 0 and is assigned to the new local variable a.
We can solve this problem by declaring variables before assigning values.
Function myFunc () {let a _ r b; a = b = 0;} myFunc ()
thirty-six。 A brief introduction to the garbage collection mechanism of V8 engine
The garbage collection mechanism of V8 is based on the generational recycling mechanism, which is also based on the generational hypothesis, which has two characteristics: one is that newborn objects tend to die early, and the other is that undead objects live longer. Based on this hypothesis, the V8 engine divides memory into the new generation and the old generation. Newly created objects or objects that have experienced garbage collection only once are called Cenozoic. Objects that have experienced multiple garbage collection are called the old generation. The new generation is divided into two spaces: From and To, and To is generally idle. When the From space is full, the Scavenge algorithm is executed for garbage collection. When we execute the garbage collection algorithm, the application logic will stop and continue when the garbage collection is over. The algorithm is divided into three steps: (1) first check the living object in From space, if the object survives, determine whether the object meets the conditions for promotion to the old age, and if it meets the conditions, it is promoted to the old age. Move the To space if the condition is not met. (2) if the object does not survive, release the space of the object. (3) finally, the roles of From space and To space are exchanged. There are two conditions for the promotion of the new generation object to the old generation: (1) the first is to judge whether the object has been recycled once by Scavenge. If experienced, the object is copied from the From space to the old age; if not, to the To space. (2) the second is whether the memory usage ratio of To space exceeds the limit. When an object is copied from From space to To space, if the To space is used more than 25%, the object is directly promoted to the older generation. The main reason for setting 25% is that after the end of the algorithm, the positions of the two spaces will be exchanged. If the memory of the To space is too small, it will affect the subsequent memory allocation. In the old age, the methods of mark elimination and mark compression were adopted. Tag cleanup first marks the objects that are alive in memory, and then erases those objects that are not tagged. Because the mark is cleared, it will cause a lot of memory fragmentation, which is not convenient for the later memory allocation. Therefore, the mark compression method is introduced to solve the problem of memory fragmentation. Because the logic of application is suspended during garbage collection, for the new generation of methods, due to the small memory, each pause will not be too long, but for the older generation, each time of garbage collection is long, the pause will have a great impact. In order to solve this problem, V8 introduces the method of incremental marking, dividing the process of a pause into multiple steps, and let the running logic execute for a while after each small step, so that it runs alternately.
Related information:
"deeply understand the garbage collection principle of V8"
Garbage collection in JavaScript
thirty-seven。 What actions can cause memory leaks?
1. Unexpected global variable
two。 Forgotten timer or callback function
3. Break away from the citation of DOM
4. Closure
The first situation is that we accidentally create a global variable because we use an undeclared variable, so that the variable remains in memory and cannot be recycled.
The second case is that we set the setInterval timer and forget to cancel it. If the looping function has a reference to an external variable, then the variable will remain in memory and cannot be recycled.
The third case is that we get a reference to the DOM element, and the latter element is deleted, and because we keep the reference to this element, it cannot be recycled.
The fourth case is the unreasonable use of closures, resulting in some variables being left in memory all the time.
Related information:
JavaScript memory leak tutorial
"Type 4 JavaScript memory leaks and how to avoid them"
"stop the occurrence of four types of memory leaks in js"
"typical memory leaks in javascript and troubleshooting methods for chrome"
The following 38 items and 46 items are the basic knowledge points often taken in ECMAScript 2015 (ES6).
thirty-eight。 What is ECMAScript?
ECMAScript is the standard for scripting languages, which means that JavaScript follows the specification changes in the ECMAScript standard because it is the blueprint for JavaScript.
Both ECMAScript and Javascript are essentially related to a language, one is the name of the language itself, and the other is the constraint of the language.
It's just that the man who invented JavaScript (Netscape company) gave something to ECMA (European Computer Manufacturers Association). This man laid down his standard, because there was java language at that time, and he wanted to emphasize that this thing was made by ECMA, so such a magical thing was born, and its name was called ECMAScript.
JavaScript = ECMAScript + DOM + BOM (think of yourself as a generalized JavaScript)
JavaScript has to do what ECMAScript says!
JavaScript (narrow JavaScript) asks ECMAScript if I can do anything! If I can't, I'm wrong! Yes, I am right!
-- suddenly feel that JavaScript has no dignity, so why should someone come out to restrain himself?
Whether that person is aggrieved or aggrieved, he is created entirely because he wants to restrain JavaScript.
thirty-nine。 What are the new features of ECMAScript 2015 (ES6)?
Block scope
Class
Arrowhead function
Template string
Enhanced object literally
Object deconstruction
Promise
Module
Symbol
Agent (proxy) Set
Function default parameter
Rest and deployment
forty。 What is the difference between `var`, `let` and `var`?
Variables declared by var are mounted on window, while variables declared by let and const are not:
Var declares that there is variable promotion in variables, and there is no variable promotion in let and const:
Console.log (a); / / undefined = > a has been declared unassigned, and the default value is var a = 100; console.log (b); / / error: b is not defined = = > cannot find b this variable let b = 10; console.log (c); / / error: c is not defined = > the variable const c = 10 cannot be found
Let and const declarations form block scope
If (1) {var a = 100; let b = 10;} console.log (a) / / 100 console.log (b) / / error: b is not defined = = > cannot find the variable b-if (1) {var a = 100; const c = 1;} console.log (a) / / 100 console.log (c) / / error: c is not defined = = > the variable c cannot be found
Let and const cannot declare variables with the same name in the same scope, but var can
Var 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 dead zone
Var a = 100; if (1) {a = 10; / / if an is declared using let/const in the current block scope, assigning an at 10:00 will only find the variable an in the current scope, / / and at this time, it is not yet time to declare, so the console Error:an is not defined let a = 1;}
Const
/ * * 1. Once it is declared that a value must be assigned, you cannot use null to occupy a place. * * 2. Cannot be modified after declaration * * 3. If you are declaring compound type data, you can modify its properties * * / const a = 100; const list = []; list [0] = 10; console.log (list); / / [10] const obj = {alist 100}; obj.name = 'apple'; obj.a = 10000; console.log (obj); / / {a000 console.log console.log application'}
forty-one。 What is the arrowhead function?
Arrow function expressions have a more concise syntax than function expressions and do not have their own this,arguments,super or new.target. The arrow function expression is more suitable for places where anonymous functions are needed, and it cannot be used as a constructor.
/ / ES5 Version var getCurrentDate = function () {return new Date ();} / ES6 Version const getCurrentDate = () = > new Date ()
In this example, the ES5 version has the function () {} declaration and the return keyword, which are required to create the function and return the value, respectively. In the arrow function version, we only need () parentheses, not the return statement, because if we only have one expression or value to return, the arrow function will have an implicit return.
/ / ES5 Version 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, we can omit the parentheses.
Const getArgs = () = > arguments const getArgs2 = (... rest) = > rest
The arrow function cannot access the arguments object. So calling the first getArgs function throws an error. Instead, we can use the rest parameter to get all the parameters passed in the arrow function.
Const data = {result: 0, nums: [1,2,3,4,5], computeResult () {/ / where "this" refers to the "data" object const addAll = () = > {return this.nums.reduce ((total, cur) = > total + cur, 0)}; this.result = addAll ();}}
The arrow function does not have its own this value. It captures the this value of the lexical scope function, which in this example will copy the this value in the computeResult method, which is the window object if we declare the arrow function in the global scope.
forty-two。 What is a class?
Class (class) is a new way to write constructors in JS. It is the syntax sugar that uses the constructor, which is still prototype and prototype-based inheritance at the bottom.
/ ES5 Version 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 the method and inherit from another class.
/ / ES5 Version 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" Person "return" [object Employee] ";}}
So how do we know it uses prototypes internally?
Class Something {} 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 implements class, what does it mean for JavaScript front-end development? "
Basic Grammar of Class
forty-three。 What is a template string?
Template strings are a new way to create strings in JS. We can serialize the template by using backquotes.
/ / ES5 Version var greet ='Hi I\ m Mark'; / / ES6 Version let greet = `Hi I\'m Mark`
In ES5, we need to use some escape characters to achieve the effect of multiple lines, but we don't need to be so troublesome in template strings:
/ / ES5 Version var lastWords ='\ n' +'I\ n' +'Am\ n' + 'Iron Man\ n`; / / ES6 Version let lastWords = `I Am Iron Man `
In the ES5 version, we need to add\ nto add a new line in the string. We don't need to do this in the template string.
/ / ES5 Version function greet (name) {return 'Hello' + name +'!;} / / ES6 Version function greet (name) {return `Hello ${name}! `;}
In the ES5 version, if you need to add an expression or value to a string, you need to use the + operator. In the template string s, we can embed an expression using ${expr}, which makes it cleaner than the ES5 version.
forty-four。 What is object deconstruction?
Object destructing is a new and more concise way to get or extract values from an object or array. Suppose you have the following objects:
Const employee = {firstName: "Marko", lastName: "Polo", position: "Software Developer", yearHired: 2017}
The early way to get a property from an object is to create a variable with the same name as the object property. This approach is troublesome because we have to create a new variable for each attribute. Suppose we have a large object with many properties and methods, and it would be troublesome to extract attributes in this way.
Var firstName = employee.firstName; var lastName = employee.lastName; var position = employee.position; var yearHired = employee.yearHired
Using deconstruction makes the syntax much simpler:
{firstName, lastName, position, yearHired} = employee
We can also alias the attribute:
Let {firstName: fName, lastName: lName, position, yearHired} = employee
Of course, if the attribute value is undefined, we can also specify the default value:
Let {firstName = "Mark", lastName: lName, position, yearHired} = employee
forty-five。 What is the `Set` object and how does it work?
Set objects allow you to store unique values of any type, whether they are original values or object references.
We can use the Set constructor to create an Set instance.
Const set1 = new Set (); const set2 = new Set (["a", "b", "c", "d", "d", "e"])
We can use the add method to add a new value to the Set instance, because the add method returns a Set object, so we can use add again in a chained manner. If a value already exists in the Set object, it will no longer be added.
Set2.add ("f"); set2.add ("g"). Add ("h"). Add ("I"). Add ("j"). Add ("k"). Add ("k"); / / the latter "k" will not be added to the set object because it already exists
We can use the has method to check whether a specific value exists in the Set instance.
Set2.has ("a") / / true set2.has ("z") / / true
We can use the size property to get the length of the Set instance.
Set2.size / / returns 10
You can use the clear method to delete data in Set.
Set2.clear ()
We can use the Set object to remove duplicate elements from the array.
Const numbers = [1, new Set 2, 3, 4, 5, 6, 7, 8, 5]; const uniqueNums = [. New Set (numbers)]; / / [1, 2, 4, 4, 5, 5, 7, 7, 5]
There is also WeakSet, which, like Set, is a collection of values that do not repeat. However, members of a WeakSet can only be objects, not values of other types. Objects in WeakSet are weak references, that is, the garbage collection mechanism does not take into account WeakSet's reference to the object.
Map data structure. It is similar to objects and is also a collection of key-value pairs, but the scope of "keys" is not limited to strings, and all types of values (including objects) can be used as keys.
The WeakMap structure, similar to the Map structure, is also a collection used to generate key-value pairs. However, WeakMap only accepts objects as key names (except null) and does not accept other types of values as key names. And the object pointed to by the key name of WeakMap is not included in the garbage collection mechanism.
forty-six。 What is Proxy?
Proxy is used to modify the default behavior of certain operations, which is equivalent to making changes at the language level, so it belongs to a kind of "metaprogramming", that is, programming the programming language.
Proxy can be understood as setting up a layer of "interception" in front of the target object, and external access to the object must first be intercepted through this layer, so it provides a mechanism to filter and rewrite external access. The original meaning of the word Proxy is agent, which is used here to mean to "delegate" certain operations, which can be translated as "agent".
High-energy early warning, the following 47064 items are more difficult advanced knowledge and related handwritten implementation in JavaScript. Please take your time and detail them.
forty-seven。 Write a general event listener function
Const EventUtils = {/ / depending on capabilities, use dom0 | | dom2 | | bind events / / add events 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 event 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;}, / / get the reference to the event object, get all the information about the event, and ensure that you can use event getEvent: function (event) {return event | | window.event at any time. }, / / block events (mainly event bubbling, because IE does not support event capture) 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;}
forty-eight。 What is functional programming? What are the features of JavaScript that make it a candidate for functional languages?
Functional programming (usually abbreviated as FP) is the process of building software by writing pure functions to avoid shared state, variable data, and side effects. Numerical programming is declarative rather than imperative, and the state of the application flows through pure functions. In contrast to object-oriented programming, the state of an application in object-oriented is usually shared and coexisted with methods in the object.
Functional programming is a programming paradigm, which means that it is a way of thinking about software construction based on some basic definition principles (as listed above). Of course, other examples of programming paradigms include object-oriented programming and procedural programming.
Functional code tends to be simpler, more predictable, and easier to test than imperative or object-oriented code-but if you are not familiar with it and the common patterns associated with it, functional code may also look more dense and messy, and the relevant literature is difficult for newcomers to understand.
forty-nine。 What is a higher-order function?
A higher-order function is just a function that takes a function as a parameter or a return value.
Function higherOrderFunction (param,callback) {return callback (param);}
fifty。 Why are functions called first-class citizens?
In JavaScript, functions not only have all the traditional ways of using functions (declarations and calls), but can also be like simple values:
Assignment (var func = function () {}),
Pass parameters (function func (x _ callback) {callback ();}),
Return (function () {return function () {}})
Such a function is also called a first-level function (First-class Function). Not only that, the function in JavaScript also acts as the constructor of the class and is also an instance of the Function class (instance). Such multiple identities make the function of JavaScript very important.
fifty-one。 Manually implement `Array.prototype.map method `
The map () method creates a new array, which results in the result that each element in the array calls a provided function.
Function map (arr, mapCallback) {/ / first, check whether the passed parameters are correct. If (! Array.isArray (arr) | |! arr.length | | typeof mapCallback! = = 'function') {return [];} else {let result = []; / / every time we call this function, we create a 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)); // 将 mapCallback 返回的结果 push 到 result 数组中 } return result; } } 52. 手动实现`Array.prototype.filter`方法 filter()方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。 function filter(arr, filterCallback) { // 首先,检查传递的参数是否正确。 if (!Array.isArray(arr) || !arr.length || typeof filterCallback !== 'function') { return []; } else { let result = []; // 每次调用此函数时,我们都会创建一个 result 数组 // 因为我们不想改变原始数组。 for (let i = 0, len = arr.length; i < len; i++) { // 检查 filterCallback 的返回值是否是真值 if (filterCallback(arr[i], i, arr)) { // 如果条件为真,则将数组元素 push 到 result 中 result.push(arr[i]); } } return result; // return the result array } } 53. 手动实现`Array.prototype.reduce`方法 [reduce()]() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。 function reduce(arr, reduceCallback, initialValue) { // 首先,检查传递的参数是否正确。 if (!Array.isArray(arr) || !arr.length || typeof reduceCallback !== 'function') { return []; } else { // 如果没有将initialValue传递给该函数,我们将使用第一个数组项作为initialValue let hasInitialValue = initialValue !== undefined; let value = hasInitialValue ? initialValue : arr[0]; 、 // 如果有传递 initialValue,则索引从 1 开始,否则从 0 开始 for (let i = hasInitialValue ? 0 : 1, len = arr.length; i < len; i++) { value = reduceCallback(value, arr[i], i, arr); } return value; } } 54. js的深浅拷贝 JavaScript的深浅拷贝一直是个难点,如果现在面试官让我写一个深拷贝,我可能也只是能写出个基础版的。所以在写这条之前我拜读了收藏夹里各路大佬写的博文。具体可以看下面我贴的链接,这里只做简单的总结。 浅拷贝: 创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。 深拷贝: 将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。 浅拷贝的实现方式: Object.assign() 方法: 用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。 Array.prototype.slice():slice() 方法返回一个新的数组对象,这一对象是一个由 begin和end(不包括end)决定的原数组的浅拷贝。原始数组不会被改变。 拓展运算符`…`: let a = { name: "Jake", flag: { title: "better day by day", time: "2020-05-31" } } let b = {...a}; 深拷贝的实现方式: 乞丐版: JSON.parse(JSON.stringify(object)),缺点诸多(会忽略undefined、symbol、函数;不能解决循环引用;不能处理正则、new Date()) 基础版(面试够用): 浅拷贝+递归 (只考虑了普通的 object和 array两种数据类型) function cloneDeep(target,map = new WeakMap()) { 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 } } 终极版: const 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 = /(? { cloneTarget.set(key, clone(value, map)); }); return cloneTarget; } // 克隆对象和数组 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% of people don't know)
fifty-five。 Handwritten call, apply and bind functions
The implementation steps of the call function:
1. To determine whether the calling object is a function, even if we are defined on the prototype of the function, it may be called using call and so on.
two。 Determines whether the incoming context object exists, and if not, sets it to window.
3. Process the incoming parameters and intercept all the 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 return result.
6. Delete the properties you just added.
7. Returns the result.
/ / the call function implements Function.prototype.myCall = function (context) {/ / determines the calling object if (typeof this! = = "function") {console.error ("type error");} / / gets the parameter let args = [... arguments] .slice (1), result = null; / / determines whether context is passed, and if it is not passed, set it to window contextcontext = context | | window / / set the calling function as the method of the object context.fn = this; / / call the function result = context.fn (.. ARGs); / / delete the attribute delete context.fn; return result;}
The implementation steps of the apply function:
1. To determine whether the calling object is a function, even if we are defined on the prototype of the function, it may be called using call and so on.
two。 Determines whether the incoming context object exists, and if not, sets it to window.
3. Use the function as an attribute of the context object.
4. Determine whether the parameter value is passed in
4. Use the context object to call this method and save the return result.
5. Delete the attribute you just added
6. Return the result
/ / apply function implementation Function.prototype.myApply = function (context) {/ / determine whether the calling object is a function if (typeof this! = = "function") {throw new TypeError ("Error");} let result = null; / / determine whether context exists, if not passed in, window contextcontext = context | | window; / / the method that sets the function as the object context.fn = this / / call the method if (arguments [1]) {result = context.fn (... arguments [1]);} else {result = context.fn ();} / / delete the attribute delete context.fn; return result;}
The implementation steps of the bind function:
1. To determine whether the calling object is a function, even if we are defined on the prototype of the function, it may be called using call and so on.
two。 Save a reference to the current function and get the rest of the incoming parameter values.
3. Create a function to return
4. Apply is used inside the function to bind function calls. You need to determine whether the function is used as a constructor. In this case, you need to pass the this of the current function to the apply call, and in other cases, pass in the specified context object.
/ / bind function implementation Function.prototype.myBind = function (context) {/ / determine whether the calling object is a function if (typeof this! = = "function") {throw new TypeError ("Error");} / / get the parameter var args = [. Arguments] .slice (1), fn = this Return function Fn () {/ / pass in different binding values return fn.apply (this instanceof Fn? This: context, args.concat (... arguments);};}
Reference article:
"handwritten call, apply and bind functions"
"Simulation implementation of call and apply in depth of JavaScript"
fifty-six。 The realization of Corialization of function
/ / function Corialization refers to a technique that converts a function that uses multiple arguments into a series of functions that use one parameter. Function curry (fn, args) {/ / get the parameter length required by the function let length = fn.length; argsargs = args | | []; return function () {let subArgs = args.slice (0); / / concatenate all existing parameters for (let I = 0; I)
< arguments.length; i++) { subArgs.push(arguments[i]); } // 判断参数的长度是否已经满足函数所需参数的长度 if (subArgs.length >= length) {/ / if satisfied, execute the function return fn.apply (this, subArgs);} else {/ / if not satisfied, recursively return the Corialized function and wait for the input of the parameter return curry.call (this, fn, subArgs);}} } / / es6 implements function curry (fn,... args) {return fn.length {console.log (1) setTimeout () = > {console.log (2) setTimeout () = > {console.log (3)}, 3000)}, 2000)}, 1000)
This is a typical callback hell. The above code does not seem to be easy to read and maintain, and once there are more events, it is even more messy, so Promise and async/await are proposed in es6 to solve the callback hell problem. Of course, the callback function has several other disadvantages, such as the inability to use try catch to catch errors and to return directly. The next two are to solve these problems. Let's move on.
fifty-nine。 What is Promise? can you implement it by hand?
Promise, translated as a promise, promises that it will give you a result over time. Programmatically speaking, Promise is a solution to asynchronous programming. The following is the description of Promise in MDN:
The Promise object is a proxy object (a proxy value), and the value of the proxied object may be unknown when the Promise object is created. It allows you to bind the corresponding handlers for the success and failure of an asynchronous operation. This allows asynchronous methods to return values like synchronous methods, but not immediately return the final execution result, but a promise object that represents future results.
A Promise has the following states:
Pending: the initial state, which is neither success nor failure.
Fulfilled: this means that the operation completed successfully.
Rejected: it means that the operation failed.
Once this commitment changes from a waiting state to another state, the state can never be changed, that is, once the state becomes fulfilled/rejected, it cannot be changed again.
Maybe people don't understand Promise just by looking at the concept. Let's take a simple chestnut.
If I have a girlfriend, next Monday is her birthday, I promised her birthday a surprise, then from now on this commitment will enter the waiting state, waiting for next Monday, and then the state will change. If I surprise my girlfriend next Monday as promised, then the status of the promise will be changed from pending to fulfilled, indicating that the promise has been successfully fulfilled. Once this is the result, there will be no other results, that is, the status will not change. On the other hand, if I work overtime because I am too busy at work that day and forget about it, and the surprise is not fulfilled, the status will be changed from pending to rejected, and the time cannot be turned back, so the state can no longer be changed.
Last time we said that Promise can solve the problem of callback hell, yes, the Promise object in pending state will trigger the fulfilled/rejected state, and once the state changes, the then method of the Promise object will be called; otherwise, catch will be triggered. Let's rewrite the code for the previous callback to hell:
New 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)})
In fact, Promise also has some shortcomings, such as unable to cancel Promise, errors need to be caught through the callback function.
Promise handwritten implementation, interview sufficient version:
Function myPromise (constructor) {let self=this; self.status= "pending" / / define the initial state before the state change self.value=undefined;// defines the state self.reason=undefined when the state is resolved / / define the state function resolve (value) {/ / two = "pending" when the state is rejected, ensuring that the change of the state is irreversible if (self.status=== "pending") {self.value=value; self.status= "resolved" }} function reject (reason) {/ / two = "pending" to ensure that the state change is irreversible if (self.status=== "pending") {self.reason=reason; self.status= "rejected";}} / / capture construction exception try {constructor (resolve,reject) } catch (e) {reject (e);}} / / defines the 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:}}
There are other knowledge about Promise, such as the use of Promise.all (), Promise.race (), etc., which are no longer expanded because of the space. For more information, please see the following article.
Related information:
Hardcore JS has an in-depth understanding of asynchronous solutions: https://juejin.im/post/5e4613b36fb9a07ccc45e339#heading-69
Promises/A+ specification: https://www.ituring.com.cn/article/66566#
sixty。 What is `Iterator` and what is its function?
Iterator is a prerequisite for understanding Article 24. Maybe I don't have enough IQ. Iterator and Generator still have little knowledge after watching it many times. Even if they understood it at that time, they forgot all about it after a while.
Iterator (iterator) is an interface, or a specification. Provide a unified access mechanism for different data structures. Any data structure can be traversed as long as the Iterator interface is deployed (that is, all members of the data structure are processed in turn).
Iterator syntax:
Const obj = {[Symbol.iterator]: function () {}}
The [Symbol.iterator] attribute name is written in a fixed way, and as long as an object with this property is owned, it can be traversed as an iterator.
The iterator traversal method is to first get a pointer to the iterator, which initially points to the first piece of data, and then changes the pointer to the next piece of data by calling the next method.
Each time the next returns an object that 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, and true indicates that the traversal is over.
There are three functions of Iterator:
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
Provide a unified and simple access interface for various data structures.
Enables the members of the data structure to be arranged in a certain order
ES6 created a new traversal command, for. Of loop, Iterator interface is mainly for for. Of consumption.
Traverse the process:
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
Creates a pointer object that points to the starting position of the current data structure. In other words, the traversal object is essentially a pointer object.
The first time you call the next method of the pointer object, you can point the pointer to the first member of the data structure.
The second time you call the next method of the pointer object, the pointer points to the second member of the data structure.
The next method of the pointer object is called until it points to the end of the data structure.
Each time the next method is called, information about the current member of the data structure is returned. Specifically, it returns an object that contains value and done properties. Where the value property is the value of the current member and the done property is a Boolean value indicating whether the traversal ends.
Let arr = [{num:1}, 2Power3] let it = arr [Symbol.iterator] () / / get the iterator 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}
sixty-one。 What is the `Generator` function and what is its function?
The Generator function can be said to be the specific implementation of the Iterator interface. The most important feature of Generator is that it can control the execution of functions.
Function * foo (x) {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, and let's analyze its execution:
First, when the Generator function is called, it returns an iterator.
When the first next is executed, the passing parameter is ignored and the function is paused at yield (x + 1), so 5 + 1 = 6 is returned.
When the second next is executed, the parameter passed in is equal to the return value of the previous yield, and if you do not pass the parameter, yield always returns undefined. At this point let y = 2 * 12, so the second yield equals 2 * 12 / 3 = 8
When the third next is executed, the passed parameters are passed to z, so z = 13, x = 5, y = 24, and the sum equals 42
Generator function generally does not see much, in fact, it has something to do with it, and will generally be used in conjunction with the co library. Of course, we can solve the problem of callback hell through the Generator function.
sixty-two。 What is `async/ Await` and how it works, and what are its advantages and disadvantages?
Async/await is a new method of writing asynchronous or non-blocking code based on Promise, which is generally regarded as the ultimate and most elegant solution for JS asynchronous operations. It is more readable and concise than Promise and callbacks. After all, then () is annoying all the time.
Async means asynchronous, while await is the abbreviation of async wait, that is, asynchronous waiting.
So it is semantically easy to understand that async is used to declare that an function is asynchronous, while await is used to wait for an asynchronous method execution to complete.
If a function adds async, then the function will return a Promise
Async function test () {return "1"} console.log (test ()) / /-> Promise {: "1"}
You can see that the output is a Promise object. So, the async function returns a Promise object, and if you return a direct quantity directly in the async function, async will return the direct quantity as a Promise object through PromIse.resolve ().
It can handle then chain better than Promise,async/await.
Function takeLongTime (n) {return new Promise (resolve = > {setTimeout () = > resolve (n + 200), n);} function step1 (n) {console.log (`step2 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 use Promise and async/await to handle these three steps, respectively.
Use Promise
Function doIt () {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 the previous Promise implementation, but does the code look much clearer, elegant and clean, almost like synchronous code.
The await keyword can only be used in async function. Using the await keyword in any function that is not async function throws an error. The await keyword waits for the right expression (possibly a Promise) to return before executing the next line of code.
Advantages and disadvantages:
The advantage of async/await is that it handles the call chain of then, can write code more clearly and accurately, and can also elegantly solve the callback hell problem. Of course, there are some disadvantages, because await transforms asynchronous code into synchronous code, and if multiple asynchronous code has no dependencies but uses await, it will lead to performance degradation.
Reference article:
Hardcore JS has an in-depth understanding of asynchronous solutions: https://juejin.im/post/5e4613b36fb9a07ccc45e339#heading-69
The above two hundred and twenty-five are the main asynchronous solutions in JavaScript. There are difficulties, and you need to figure it out and practice.
sixty-three。 What is the principle of instanceof and how to implement it?
Instanceof can correctly determine the type of object, because the internal mechanism is to determine whether the type prototype can be found in the prototype chain of the object.
Implement instanceof:
First get the prototype of the type
And then get the prototype of the object
Then loop to determine whether the prototype of the object is equal to the prototype of the type until the prototype of the object is null, because the prototype chain is ultimately null
Function myInstanceof (left, right) {let prototype = right.prototype leftleft = left.__proto__ while (true) {if (left = null | | left = undefined) return false if (prototype = = left) return true leftleft = left.__proto__}}
sixty-four。 Throttling and Anti-shaking of js
Function anti-shake means that the callback is performed after the event is triggered n seconds, and if the event is triggered again within n seconds, the time is re-timed. This can be used on some click request events to avoid sending multiple requests to the backend because of multiple clicks by the user.
Function throttling means to specify a unit time in which only one callback function that triggers an event can be executed. If an event is triggered multiple times in the same unit time, it will only take effect once. Throttling can be used in the event listening of the scroll function to reduce the frequency of event calls through event throttling.
/ / implementation of anti-shake function function debounce (fn, wait) {var timer = null; return function () {var context = this, args = arguments; / / if there is a timer at this time, cancel the previous timer if (timer) {clearTimeout (timer); timer = null } / / set timer to execute timer = setTimeout (() = > {fn.apply (context, args);}, wait);};} / / function throttling implementation after the event interval is specified; function throttle (fn, delay) {var preTime = Date.now () Return function () {var context = this, args = arguments, nowTime = Date.now (); / / if the interval exceeds the specified time, the function is executed. If (nowTime-preTime > = delay) {preTime = Date.now (); return fn.apply (context, args);}};}
sixty-five。 What is a design pattern?
1. Concept
Design pattern is a set of repeatedly used, well-known, classified and cataloged summary of code design experience. The purpose of using design patterns is to reuse code, make it easier for others to understand, and ensure code reliability. There is no doubt that design patterns are win-win for others and systems. Design patterns make the code really engineering. Design patterns are the cornerstone of software engineering, just like the bricks and stones of a building.
two。 Design principle
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
S-Single Responsibility Principle single responsibility principle
A program only does one thing well.
If the function is too complex, separate it, and each part remains independent.
2. O-OpenClosed Principle Open / closed principle
Open to extension and closed to modification
When increasing demand, extend new code instead of modifying existing code
3. L-Liskov Substitution Principle Richter substitution principle
Subclasses can override parent classes
Where the parent class can appear, the subclass can appear.
4. I-Interface Segregation Principle interface isolation principle
Keep the interface single and independent
Similar to the principle of single responsibility, here we pay more attention to the interface.
5. D-Dependency Inversion Principle dependency inversion principle
Interface-oriented programming that depends on abstraction rather than on tools
The user only focuses on the interface but not on the implementation of the concrete class.
3. Types of design patterns
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
Structural pattern (Structural Patterns): simplifies the design of a system by identifying simple relationships between components in the system.
Creative mode (Creational Patterns): handles the creation of objects, creating objects in an appropriate way according to the actual situation. Conventional object creation may cause design problems or increase the complexity of the design. The creative pattern solves the problem by controlling the creation of objects in some way.
3. Behavioral patterns (Behavioral Patterns): used to identify and implement common interaction patterns between objects, thus increasing the flexibility of these interactions.
sixty-six。 9 common front-end design patterns
1. Appearance mode (Facade Pattern)
Appearance pattern is one of the most common design patterns, which provides a unified high-level interface for a group of interfaces in the subsystem, making the subsystem easier to use. In short, the design pattern is to abstract the complex logic in multiple subsystems, so as to provide a more unified, more concise, easier-to-use API. Many of our commonly used frameworks and libraries basically follow the design pattern. For example, JQuery abstracts and encapsulates complex native DOM operations and eliminates the compatibility problems between browsers, thus providing a more advanced and easier-to-use version. In fact, in our daily work, we often use appearance patterns for development, but we just don't know it.
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
Compatible browser event binding
Let 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}}
two。 Encapsulation interface
Let myEvent = {/ /... Stop: e = > {e.stopPropagation (); e.preventDefault ();}}
Scene
At the beginning of the design, we should consciously separate two different layers, such as the classic three-tier structure, and establish a facade Facade between the data access layer and the business logic layer, the business logic layer and the presentation layer.
In the development phase, subsystems often become more and more complex because of continuous refactoring and evolution. Adding appearance Facade can provide a simple interface and reduce the dependence between them.
When maintaining a large legacy system, it may already be difficult to maintain, so it is very appropriate to use appearance Facade to develop an appearance Facade class for the department system, which provides a clearer interface for poorly designed and highly complex legacy code, allowing the new system to interact with Facade objects, and Facade to interact with all the complex work of legacy code.
Advantages
Reduce system interdependence.
Increase flexibility.
Improved security
Shortcoming
Do not comply with the principle of opening and closing, if it is troublesome to change things, it is not appropriate to inherit and rewrite.
two。 Agent mode (Proxy Pattern)
Is to provide a substitute or placeholder for an object to control access to it
Suppose that when A receives flowers when he is in a good mood, Xiao Ming has a chance of success in confessing his love.
60%, and when A receives flowers when he is in a bad mood, the success rate of Xiao Ming's confession is infinitely close to 0.
Xiao Ming and A have only known each other for two days and can't tell when An is in a good mood. If you give flowers to A, flowers at the wrong time.
It is very likely to be thrown away directly. This bouquet of flowers was bought by Xiao Ming after eating instant noodles for seven days.
But A's friend B knows A very well, so Xiao Ming just gives the flowers to BMagee B will monitor A's mood change and then choose
Choose A to hand over the flowers to A when you are in a good mood. The code is as follows:
Let 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 ('received flowers' + flower)} ListenGoodMood: function (fn) {setTimeout (function () {fn ()}, 1000)} xiaoming.sendFlower (B)
Scene
HTML element event proxy
1 2 3 let ul = document.querySelector ('# ul'); ul.addEventListener ('click', event = > {console.log (event.target);})
Ruan Yifeng Proxy, proxy of ES6
JQuery.proxy () method
Advantages
The proxy mode can separate the proxy object from the called object, which reduces the coupling degree of the system. The proxy pattern acts as an intermediary between the client and the target object, which can protect the target object.
The proxy object can expand the function of the target object; it can be done by modifying the proxy object, which conforms to the principle of opening and closing.
Shortcoming
The speed of processing requests may be different, and there is overhead in indirect access.
3. Factory mode (Factory Pattern)
The factory pattern defines an interface for creating objects, and the subclass determines which class to instantiate. This pattern delays the instantiation of a class to a subclass. Subclasses can override interface methods to specify their own object type when created.
Class Product {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 subsystem to be strongly coupled to the larger object, but you want the runtime to choose from many subsystems, then the factory pattern is an ideal choice.
Simply encapsulate the new operation, and you should consider whether to use factory mode when you encounter new
Different instances need to be created depending on the specific environment, and these instances all have the same behavior. At this time, we can use the factory pattern to simplify the implementation process, and at the same time, we can also reduce the amount of code required for each object, which helps to eliminate the coupling between objects and provide greater flexibility.
Advantages
The process of creating an object can be complex, but we only need to care about the result.
The constructor is separated from the creator, which accords with the "opening and closing principle".
A caller wants to create an object by knowing its name.
High scalability, if you want to add a product, just extend a factory class.
Shortcoming
When adding new products, it is necessary to write new specific product classes, which increases the complexity of the system to a certain extent.
Considering the expansibility of the system, it is necessary to introduce the abstraction layer, which is defined in the client code, which increases the abstraction and difficulty of understanding of the system.
When don't use it?
When applied to the wrong type of problem, this pattern introduces 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, I would recommend using explicit constructors to avoid unnecessary overhead.
The fact that the object creation process is efficiently abstracted behind an interface also poses problems for unit tests that depend on how complex the process can be.
4. Singleton mode (Singleton Pattern)
As the name implies, the maximum number of instances of Class in the singleton pattern is 1. The singleton pattern comes in handy when an object is needed to perform certain tasks throughout the system. In other scenarios, try to avoid the use of singleton mode, because singleton mode will introduce global state, and a healthy system should avoid introducing too much global state.
To implement the singleton pattern, you need to solve the following problems:
How can I be sure that there is only one instance of Class?
How can I easily access the only instance of Class?
How does Class control the instantiation process?
How to limit the number of Class instances to 1?
We generally solve the above problems by implementing the following two points:
Hide the constructor of Class to avoid multiple instantiations
Create / get a unique instance by exposing a getInstance () method
The singleton pattern in Javascript can be implemented in the following ways:
/ / Singleton constructor const FooServiceSingleton = (function () {/ / hidden Class constructor function FooService () {} / / uninitialized singleton object let fooService; return {/ / create / get singleton object function getInstance: function () {if (! fooService) {fooService = new FooService ();} return fooService }) ()
The key points to be realized are:
Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community
Use IIFE to create a local scope and execute it immediately
GetInstance () is a closure that saves the singleton object in the local scope and returns.
We can verify whether the following singleton object is created successfully:
Const fooService1 = FooServiceSingleton.getInstance (); const fooService2 = FooServiceSingleton.getInstance (); console.log (fooService1 = fooService2); / / true
Scenario example
Define namespaces and implement branching methods
Login box
Store in vuex and redux
Advantages
Divide namespaces and reduce global variables
Enhance modularity, organize your code under a global variable name and put it in a single location for easy maintenance
And will only be instantiated once. Simplifies debugging and maintenance of code
Shortcoming
Because the singleton mode provides a single point of access, it may lead to strong coupling between modules.
Which is not conducive to unit testing. You cannot test a class that calls a method from a singleton alone, but only as one with that singleton
Each unit is tested together.
5. Policy Mode (Strategy Pattern)
The simple description of the policy pattern is that the object has a behavior, but in different scenarios, the behavior has different implementation algorithms. Package them one by one so that they can replace each other.
Policy mode-verify form username: password: mobile number: submit / / 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 | 6 | 7 | 9] | 17 [7] | 18 [0 | 1 | 2 | 3 | 5 | 6 | 8 | 9])\ d {8} $/ .test (value)) {return errorMsg } / / Verification class class Validator {constructor () {this.cache = []} add (dom, rules) {for (let I = 0, rule; rule = rules [iTunes +]) ) {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 [iTunes +] ) {let errorMsg = validatorFunc () if (errorMsg) {return errorMsg} / / call code let registerForm = document.getElementById ('registerForm') let validataFunc = function () {let Validator = new Validator () validator.add (registerForm.userName [{strategy: 'isNoEmpty', errorMsg:' username cannot be empty'}, {strategy: 'isNoSpace', errorMsg:' not allowed to be named with blank characters'}, {strategy: 'minLength:2' ErrorMsg: 'username length cannot be less than 2 digits'}]) validator.add (registerForm.password, [{strategy: 'minLength:6', errorMsg:' password length cannot be less than 6 digits'}]) validator.add (registerForm.phoneNumber, [{strategy: 'isMobile' ErrorMsg: 'enter the correct mobile phone number format'}]) return validator.start ()} registerForm.onsubmit = function () {let errorMsg = validataFunc () if (errorMsg) {alert (errorMsg) return false}}
Scenario example
If there are many classes in a system, and the only difference between them is their 'behavior', then using the policy pattern can dynamically make an object choose one behavior among many behaviors.
A system needs to choose one of several algorithms dynamically.
Form validation
Advantages
By using the techniques and ideas of combination, delegation and polymorphism, multiple conditional selection statements can be effectively avoided.
It provides perfect support for the open-closed principle and encapsulates the algorithms in a separate strategy, making them easy to switch, understand and expand.
Using composition and delegation to give Context the ability to execute algorithms, which is also a lighter alternative to inheritance
Shortcoming
Many policy classes or policy objects will be added to the program
To use the policy mode, you must know all the strategy and the differences between each strategy so that you can choose an appropriate strategy
6. Iterator mode (Iterator Pattern)
If you see this, I'm sure you'll be impressed by the iterator Iterator in ES6, which has been briefly introduced in section 60 above. The iterator pattern simply provides a way to sequence the elements of an aggregate 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 understanding the internal structure of the data
Provides the ability to traverse containers (collections) without changing the container's interface
An iterator usually needs to implement the following interfaces:
HasNext (): determines whether the iteration is over and returns Boolean
Next (): find and return the next element
Implementing an iterator for an array of Javascript can be written as follows:
Const 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++]; } } 验证一下迭代器是否工作: const iterator = new Iterator(item); while(iterator.hasNext()){ console.log(iterator.next()); } //输出:1, red, false, 3.14 ES6提供了更简单的迭代循环语法 for…of,使用该语法的前提是操作对象需要实现 可迭代协议(The iterable protocol),简单说就是该对象有个Key为 Symbol.iterator 的方法,该方法返回一个iterator对象。 比如我们实现一个 Range 类用于在某个数字区间进行迭代: function Range(start, end) { return { [Symbol.iterator]: function () { return { next() { if (start < end) { return { value: start++, done: false }; } return { done: true, value: end }; } } } } } 验证一下: for (num of Range(1, 5)) { console.log(num); } // 输出:1, 2, 3, 4 7. 观察者模式(Observer Pattern) 观察者模式又称发布-订阅模式(Publish/Subscribe Pattern),是我们经常接触到的设计模式,日常生活中的应用也比比皆是,比如你订阅了某个博主的频道,当有内容更新时会收到推送;又比如JavaScript中的事件订阅响应机制。观察者模式的思想用一句话描述就是:被观察对象(subject)维护一组观察者(observer),当被观察对象状态改变时,通过调用观察者的某个方法将这些变化通知到观察者。 观察者模式中Subject对象一般需要实现以下API: subscribe(): 接收一个观察者observer对象,使其订阅自己 unsubscribe(): 接收一个观察者observer对象,使其取消订阅自己 fire(): 触发事件,通知到所有观察者 用JavaScript手动实现观察者模式: // 被观察者 function Subject() { this.observers = []; } Subject.prototype = { // 订阅 subscribe: function (observer) { this.observers.push(observer); }, // 取消订阅 unsubscribe: function (observerToRemove) { thisthis.observers = this.observers.filter(observer =>{return observer! = = observerToRemove;})}, / / event triggered fire: function () {this.observers.forEach (observer = > {observer.call ();});}}
Verify that the subscription was successful:
Const subject = new Subject (); function observer1 () {console.log ('Observer 1 fixing');} function observer2 () {console.log ('Observer 2 fixing');} subject.subscribe (observer1); subject.subscribe (observer2); subject.fire (); / / output: Observer 1 Firing! Observer 2 Firing!
Verify that the unsubscription was successful:
Subject.unsubscribe (observer2); subject.fire (); / / output: Observer 1 Firing!
Scene
DOM event
Document.body.addEventListener ('click', function () {console.log (' hello worldview');}); document.body.click ()
Vue response type
Advantages
Supports simple broadcast communication and automatically notifies all subscribed objects
The abstract coupling relationship between the target object and the observer can be independently extended and reused.
Increased flexibility
What the observer pattern does is decouple so that both sides of the coupling rely on abstraction rather than on concrete. So that their changes will not affect the changes on the other side.
Shortcoming
Overuse will weaken the relationship between objects and make it difficult for programs to track, maintain and understand.
8. Intermediary mode (Mediator Pattern)
In the intermediary pattern, the Mediator wraps a series of ways in which objects interact with each other, so that these objects do not have to interact directly, but the intermediaries coordinate their interaction, so that they can be loosely coupled. When the interaction between some objects changes, it will not immediately affect the interaction between other objects, ensuring that these functions can change independently of each other.
There are some similarities between the intermediary pattern and the observer pattern, which are both one-to-many relationships and centralized communication. The difference is that the intermediary pattern deals with the interaction between peer objects, while the Observer pattern deals with the interaction between Observer and Subject. The intermediary model is a bit like a dating agency, where dating partners can't communicate directly at first, but they have to screen matches through intermediaries and then decide who meets whom.
Scene
For example, shopping cart requirements, the existence of item selection form, color selection form, purchase quantity form, and so on, will trigger change events, so you can forward and process these events through intermediaries to achieve decoupling between events, and only maintain the intermediary object.
Var goods = {/ / Mobile phone inventory 'red | 32g inventory: 3,' red | 64G inventory: 1, 'blue | 32G inventory: 7,' blue | 32G inventory: 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
Chat room member class:
Function Member (name) {this.name = name; this.chatroom = null;} Member.prototype = {/ / send message send: function (message, toMember) {this.chatroom.send (message, this, toMember);}, / / receive message receive: function (message, fromMember) {console.log (`${fromMember.name} to ${this.name}: ${message}`);}}
Chat room category:
Function Chatroom () {this.members = {};} Chatroom.prototype = {/ / add member addMember: function (member) {this.members [member.name] = member; member.chatroom = this;}, / / send message send: function (message, fromMember, toMember) {toMember.receive (message, fromMember);}}
Test it:
Const 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
Advantages
The coupling between objects is loose, and the interaction between them can be changed independently.
The one-to-many relationship between intermediaries and objects replaces the reticular many-to-many relationship between objects.
If the complex coupling between objects makes maintenance difficult, and the coupling increases rapidly with the project, intermediaries are required to ReFactor the code
Shortcoming
An intermediary object will be added in the system. Because of the complexity of the interaction between objects, it is transferred to the complexity of the intermediary object, so that the intermediary object is often huge. The mediator object itself is often a difficult object to maintain.
9. Visitor Mode (Visitor Pattern)
The Visitor pattern is often used to expand third-party libraries and tools.
/ / Visitor 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 with a visit () method
Receiving Object: receive object with an accept () method
Visit (receivingObj): used for Visitor to receive a Receiving Object
Accept (visitor): for Receving Object to receive a Visitor and provide it with the ability to obtain Receiving Object data by calling Visitor's visit ()
The simple code implementation is as follows:
Receiving Object: 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);}}
Verify:
Const employee = new Employee ('bruce', 1000); const visitor = new Visitor (); employee.accept (visitor); console.log (employee.getSalary ()); / / output: 2000
Scene
The class corresponding to an object in the object structure rarely changes, but it is often necessary to define new operations on this object structure
You need to do many different and unrelated operations on objects in an object structure, and you need to avoid letting these operations "pollute" the classes of these objects, and you don't want to modify them when you add new operations.
Advantages
In accordance with the principle of single responsibility
Excellent scalability
Flexibility
Shortcoming
The disclosure of details by specific elements to visitors violates the Dimitt principle.
Violates the principle of dependency inversion, relies on concrete classes, and does not rely on abstraction.
It is difficult to change specific elements.
About 66 JavaScript interview knowledge points and answer analysis to share here, I hope the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.