001 Why do we need to write key in list components in React / Vue projects, and what is its function?#
The function of key is to determine whether two nodes are the same when updating components. If they are the same, reuse them; if not, create them anew. This is to avoid the side effects of "in-place reuse."
002 What are function throttling and function debouncing?#
The core idea of both function throttling (throttle) and function debouncing (debounce) is to optimize performance by limiting function calls, but their concepts are different:
-
Function throttling: Calls the function at specified intervals, limiting the frequency of function calls.
-
Function debouncing: For continuous function calls within a certain time period, only allows it to execute once.
Their usage scenarios are also different:
-
Function throttling: Page scroll event listening (scroll), DOM element dragging (mousemove), keyboard events (keydown).
-
Function debouncing: Text input validation sending requests, window resizing (resize).
003 What are the differences between Set, Map, WeakSet, and WeakMap?#
-
Set is similar to an array, but all member values are unique and can be iterated.
-
WeakSet members are all objects and are weak references, which can be used to store DOM nodes without causing memory leaks, and cannot be iterated.
-
Map is essentially a collection of key-value pairs and can be iterated.
-
WeakMap only accepts objects as keys (except null) and does not accept other types of values as keys; the objects pointed to by the keys cannot be iterated.
004 How does Async/Await achieve asynchronous behavior in a synchronous manner?#
Async/Await is a self-executing generate function, which is syntactic sugar for Generator. It uses the characteristics of the generate function to write asynchronous code in a "synchronous" form.
The reason Generator can implement asynchronous behavior synchronously is that it has the ability to pause and resume execution, along with data exchange and error handling mechanisms inside and outside the function body.
005 JS asynchronous solutions#
-
Callback functions, disadvantages: callback hell, cannot catch errors with try catch, cannot return.
-
Promise, disadvantages: cannot cancel Promise, errors need to be caught through callback functions.
-
Generator, needs to be used with the co library.
-
Async/await: Clear code, no need to write a large number of then chains like Promise, solves the callback hell problem.
006 Briefly explain HTTP/2 multiplexing#
In HTTP/1, each request establishes an HTTP connection, which involves 3 handshakes and 4 teardowns, a process that takes considerable time during a single request. Even with Keep-Alive enabled, which solves the issue of multiple connections, there are still two efficiency problems:
-
Serial file transfer. When requesting file a, file b can only wait for a to connect to the server, the server to process the file, and the server to return the file, which involves three steps.
-
Too many connections. Assuming the service has a maximum concurrency of 300, due to browser limitations, the maximum number of requests initiated by the browser is 6, meaning the server can handle a maximum concurrency of 50. When the 51st person accesses it, they must wait for a previous request to complete.
HTTP/2 multiplexing is designed to solve the above two performance issues. In HTTP/2, there are two very important concepts: frame and stream. A frame represents the smallest unit of data, and each frame identifies which stream it belongs to; a stream is a data stream composed of multiple frames. Multiplexing allows multiple streams to exist within a single TCP connection, meaning multiple requests can be sent, and the other party can identify which request a frame belongs to. This technology avoids the head-of-line blocking problem in older versions of HTTP and greatly improves transmission performance.
007 Discuss your thoughts on TCP three-way handshake and four-way teardown#
The three-way handshake is the minimum number of times to ensure that both the client and server know that their receiving and sending capabilities are fine.
-
First, client => server, only the server can determine that the client has sending capability.
-
Second, server => client, the client can determine that the server has sending and receiving capability.
-
Third, client => server, both parties ensure that their receiving and sending capabilities are fine.
The four-way teardown is because TCP is a full-duplex channel, meaning the client and server establish two channels:
-
Channel 1: The client's output connects to the server's input.
-
Channel 2: The client's input connects to the server's output.
Both channels can work simultaneously, so closing both channels requires four-way teardown:
-
The client closes the input channel, and the server closes the output channel.
-
The server closes the input channel, and the client closes the output channel.
008 What are the four layers of the TCP/IP protocol architecture?#
Four layers: Application layer, Transport layer, Network layer, Data link layer.
HTTP, TCP, and IP are located in the application layer, transport layer, and network layer, respectively.
009 What happens from URL input to page display?#
-
DNS resolution: Resolves the domain name to an IP address.
-
TCP connection: TCP three-way handshake.
-
Send HTTP request.
-
The server processes the request and returns the HTTP message.
-
The browser parses and renders the page.
-
Disconnect: TCP four-way teardown.
010 Introduce the HTTPS handshake process and man-in-the-middle attacks#
HTTPS handshake process:
-
The client accesses the web server using an HTTPS URL, requesting to establish an SSL connection with the server.
-
After receiving the client's request, the web server sends a copy of the website's certificate (including the public key) to the client.
-
After receiving the website certificate, the client checks the issuing authority and expiration date of the certificate. If there are no issues, it randomly generates a session key.
-
The client uses the public key to encrypt the session key and sends it to the server, which uses its private key to decrypt the session key.
-
After that, the server and client use the session key for encrypted transmission.
HTTPS man-in-the-middle attack:
-
The server sends the public key to the client.
-
The attacker intercepts the public key and keeps it for themselves.
-
The attacker then generates a forged public key and sends it to the client.
-
After receiving the forged public key, the client encrypts the session key and sends it to the server.
-
The attacker obtains the encrypted key and uses their private key to decrypt it to get the real key.
-
Simultaneously, the attacker generates a fake encrypted key and sends it to the server.
-
The server uses its private key to decrypt and obtain the fake key.
-
The server uses the fake key to encrypt transmission.
Prevention methods: The server includes the CA certificate in the public key sent to the browser, allowing the browser to verify the validity of the CA certificate.
011 What are the differences between HTTP and HTTPS?#
HTTP: Hypertext Transfer Protocol, plaintext transmission, data is unencrypted, security is relatively poor, uses port 80.
HTTPS: Secure Socket Layer Hypertext Transfer Protocol, has SSL/TLS certificates, data transmission is encrypted, security is relatively good, uses port 443, and consumes more server resources compared to HTTP.
012 Introduce repaint and reflow (Repaint & Reflow), and how to optimize them#
Browser rendering mechanism
The browser uses a flow layout model. It parses HTML into DOM, parses CSS into CSSOM, and merges DOM and CSSOM to produce a render tree. With the Render Tree, the styles of all nodes are known, then their sizes and positions on the page are calculated, and finally, the nodes are drawn onto the page.
Repaint
Repaint occurs when the geometric properties of a node change or when styles change that do not affect layout, such as outline, visibility, color, background-color, etc.
Reflow
Reflow occurs when layout or geometric properties need to change. Reflow is a key factor affecting browser performance because its changes involve updating the page layout. A reflow of one element may lead to reflows of all its child elements, subsequent nodes, and ancestor nodes.
Reflow will definitely cause repaint, but repaint does not necessarily cause reflow.
Ways to reduce repaint and reflow
CSS
-
Use transform instead of top/left.
-
Use visibility instead of display: none, as the former only causes repaint, while the latter causes reflow (changes layout).
-
Avoid using table layouts, as even a small change can cause the entire table to re-layout.
-
Avoid setting multiple layers of inline styles to prevent excessive node hierarchy.
-
Avoid writing overly specific CSS selectors.
-
Apply animation effects to elements with position set to absolute or fixed to avoid affecting the layout of other elements, resulting in only a repaint, not a reflow.
-
Avoid using CSS expressions, as they may trigger reflow.
-
Set frequently repainted or reflowed nodes as layers; layers can prevent the rendering behavior of that node from affecting other nodes, such as will-change, video, iframe, etc. The browser will automatically turn that node into a layer.
-
CSS3 hardware acceleration (GPU acceleration) can make animations like transform and opacity not cause reflow or repaint.
JavaScript
-
Avoid frequent style operations; it's best to rewrite the style property all at once or define the style list as a class and change the class property all at once.
-
Avoid frequent DOM operations; create a documentFragment, apply all DOM operations on it, and then add it to the document.
-
Avoid frequently reading properties that cause reflow/repaint; if you need to use them multiple times, cache them in a variable.
-
Use absolute positioning for elements with complex animations to detach them from the document flow; otherwise, it will cause frequent reflows of parent and subsequent elements.
013 What are the advantages and disadvantages of opacity: 0, visibility: hidden, display: none, and their applicable scenarios?#
-
opacity: 0 creates a new layer, with better performance.
-
visibility: hidden causes repaint, which is slightly better than reflow performance.
-
display: none causes reflow, with a larger performance overhead; reflow may recalculate the positions and properties of all its child elements and subsequent nodes and ancestor nodes.
014 What is the same-origin policy? How to solve cross-origin issues?#
The same-origin policy means that "protocol + domain + port" must be the same.
Ways to solve cross-origin issues:
-
CORS (Cross-Origin Resource Sharing).
-
Nginx reverse proxy.
-
JSONP: JSONP mainly utilizes the fact that the script tag has no cross-origin restrictions, supporting only the GET method.
015 Why are cookies and tokens both stored in the header, but why can't tokens be hijacked?#
-
XSS: Cross-Site Scripting attacks allow attackers to inject malicious code into other users' pages through various means. They can use scripts to obtain information and initiate requests.
-
CSRF: Cross-Site Request Forgery, simply put, is when an attacker deceives the user's browser into accessing a previously authenticated website and performing operations (such as sending emails, messages, or even financial operations like transfers and purchases). Since the browser has previously authenticated, the accessed website will consider it a legitimate user operation. CSRF cannot obtain any user information; it only deceives the user's browser to perform operations on behalf of the user.
For the above two types of attacks, if XSS is successful, both tokens and cookies can be obtained, so there is no difference between cookies and tokens in terms of XSS attacks. However, there is a difference for CSRF.
Taking the CSRF attack as an example:
-
Cookie: The user clicks a link, and the cookie is still valid, causing the backend to think it is a normal user operation and proceed with the deduction.
-
Token: The user clicks the link, but the browser will not automatically include the token, so even if a request is sent, the backend's token verification will fail, and thus no deduction will occur.
This is why only cookies can be hijacked, but tokens cannot.
Extension: How to defend?
XSS: Any input field that does not process input data may have XSS vulnerabilities. The simplest and most direct way to defend against XSS attacks is to filter user input.
CSRF:
-
Captcha.
-
Validate the HTTP Referer field.
-
Add a token instead of a cookie.
016 What are the commonly used DOM manipulation methods?#
getElementById
, getElementsByClassName
, getElementsByTagName
, getElementsByName
, querySelector
, querySelectorAll
, getAttribute
, setAttribute
.
017 What is the browser caching mechanism?#
From the perspective of cache locations, there are four types, each with its own priority. Only when all caches are checked and none are hit will a network request be made.
-
Service Worker.
-
Memory Cache.
-
Disk Cache.
-
Push Cache.
Service Worker runs in a separate thread behind the browser. When using Service Worker, the transport protocol must be HTTPS. Since Service Worker involves request interception, HTTPS is required for security. The caching mechanism of Service Worker differs from other built-in browser caching mechanisms; it allows us to freely control which files to cache, how to match caches, and how to read caches, and the cache is persistent.
The implementation of caching functionality with Service Worker generally involves three steps: first, register the Service Worker, then listen for the install event to cache the required files, so that on the next user visit, it can check for cached files by intercepting requests. If cached files exist, they can be read directly; otherwise, data will be requested.
Memory Cache refers to the cache in memory, mainly containing resources already fetched in the current page, such as styles, scripts, images, etc. Reading data from memory is certainly faster than from disk. Although memory cache is efficient, its persistence is short and will be released with the process. Once we close the tab, the cache in memory is also released.
Disk Cache refers to the cache stored on the hard disk, which is slower to read but can store anything on the disk, making it superior to Memory Cache in terms of capacity and storage duration. The vast majority of caches come from Disk Cache.
Push Cache (push cache) is content in HTTP/2, which is only used when the above three caches are not hit. It only exists during a session and is released once the session ends, and its cache time is also very short, around 5 minutes in Chrome, and it does not strictly enforce the caching directives in HTTP headers.
018 What is the difference between call and apply, and which has better performance?#
Function.prototype.apply and Function.prototype.call serve the same purpose, but differ in the parameters passed:
-
The first parameter for both specifies the context (this) for the function body.
-
The second parameter differs: apply takes an array or array-like collection as the second parameter and passes it to the function as arguments, while call takes a variable number of arguments starting from the second parameter and passes them to the function as arguments.
Call is generally faster than apply because it involves one less operation of destructuring the second parameter in apply.
With the introduction of the spread operator in ES6, even if the parameters are in an array, call can be used:
let params = [1, 2, 3, 4]
xx.call(obj, ...params)
019 Why is a 1x1 pixel transparent GIF image typically used when sending data tracking requests?#
-
No cross-origin issues.
-
Will not block page loading, affecting user experience (excluding JS/CSS file resource reporting).
-
Among all images, it has the smallest size (compared to PNG/JPG).
020 How many data types are there in JS?#
Seven: Number, String, Boolean, Object, Null, Undefined, Symbol.
021 What are the use cases for Symbol?#
-
Eliminate magic characters.
-
Use Symbol values as property names to avoid being overwritten.
-
Simulate private methods in classes: In ES6, classes do not have a private keyword to declare private methods and variables, but the uniqueness of Symbol can be used to simulate this.
const speak = Symbol();
class Person {
[speak]() {
...
}
}
022 Common HTTP status codes#
HTTP status codes are divided into five types:
Category | Description |
---|---|
1** | Informational, the server has received the request and the requester needs to continue the operation. |
2** | Success, the operation has been successfully received and processed. |
3** | Redirection, further action is needed to complete the request. |
4** | Client error, the request contains syntax errors or cannot be completed. |
5** | Server error, an error occurred while processing the request on the server. |
023 What is a media query? What is the difference between responsive design and adaptive design?#
Media Query#
Media queries allow different styles to be used under different conditions, enabling pages to achieve different rendering effects on different terminal devices.
Principle: Allows the addition of expressions for media queries (including media types and media features) to select different stylesheets, thus automatically adapting to different screen resolutions.
- Media types: Classify different devices into different types.
-
all (all devices)
-
print (printing devices)
-
screen (computer screens, tablets, smartphones)
- Media features: Describe the characteristics of devices, such as width and height.
-
width: The display area of the webpage is exactly equal to the specified width.
-
height: The display area of the webpage is exactly equal to the specified height.
-
max-width / max-height: The display area of the webpage is less than or equal to the specified width.
-
min-width / min-height: The display area of the webpage is greater than or equal to the specified width.
-
orientation: portrait (vertical mode) | landscape (horizontal mode).
Differences between Responsive Design and Adaptive Design#
- What are the differences between responsive design and adaptive design?
-
Responsive design: Develop a single interface that adapts to different clients by detecting viewport resolutions and processing code on the client side to display different layouts and content.
-
Adaptive design: Requires developing multiple interfaces, detecting viewport resolutions to determine whether the current accessing device is a PC, tablet, or mobile phone, and returning different pages accordingly.
- How to choose between responsive design and adaptive design?
-
Use responsive layout when the page is not too complex.
-
Use adaptive layout when there is a lot of information on the page and the layout is more complex.
- Advantages and disadvantages of responsive design and adaptive design?
Responsive layout
Advantages: Strong flexibility, can quickly solve the display adaptation issue for multiple devices.
Disadvantages: Lower efficiency, large workload for compatibility across devices; code can be cumbersome, potentially increasing loading time; may alter the original layout structure of the website to some extent.
Adaptive layout
Advantages: Greater compatibility for complex websites, more efficient code.
Disadvantages: The same website requires developing different pages for different devices, increasing development costs.
024 Introduce BFC and its applications#
BFC (Block Formatting Context) is a CSS rendering mode in the page box model layout, equivalent to an independent container where the elements inside do not affect the outside elements.
Ways to create BFC include:
-
float.
-
position set to absolute or fixed.
-
display set to table layout or flex layout.
-
overflow set to values other than visible (hidden, auto, scroll).
Characteristics of BFC:
-
Internal boxes are placed one after another in the vertical direction.
-
The vertical distance is determined by margins.
-
The area of BFC does not overlap with the area of floated elements.
-
When calculating the height of BFC, floating elements are also included in the calculation.
-
BFC is an independent container on the page, and its child elements do not affect outside elements.
The main functions of BFC are:
-
Clear floats.
-
Prevent margin collapse between adjacent elements within the same BFC container.
025 Overview of Event Loop?#
Event Loop refers to a mechanism in browsers or Node that solves the problem of JS single-threaded execution not blocking, which is the principle we often use for asynchronous operations.
In JS, tasks are divided into two types: macro tasks (MacroTask) and micro tasks (MicroTask).
MacroTask: setTimeout, setInterval, setImmediate, I/O, UI Rendering.
MicroTask: Promise, MutationObserver, Process.nextTick (Node exclusive).
Macro tasks are placed in the macro task queue, while micro tasks are placed in the micro task queue.
JS has a main thread and a call stack, and all tasks are placed in the call stack waiting for the main thread to execute.
The JS call stack follows the last-in-first-out rule; when a task is executed, it is added to the top of the stack, and when the execution of the stack is completed, it is removed from the top until the stack is empty.
The specific flow of JS code:
-
Execute global script synchronous code; some of these synchronous codes are synchronous statements, and some are asynchronous statements.
-
After the global script code execution is complete, the call stack will be empty.
-
Take the callback task at the front of the micro task queue and place it in the call stack for execution; after execution, it is removed from the top of the stack, and the queue length decreases by 1.
-
Continue to take the task at the front of the queue and place it in the call stack for execution, and so on, until all tasks in the micro task queue are executed. If new micro tasks are generated during the execution of micro tasks, they will be added to the end of the queue and will also be called for execution in this cycle.
-
Once all tasks in the micro task queue are executed, the micro task queue is empty, and the call stack is also empty.
-
Take the task at the front of the macro task queue and place it in the call stack for execution.
-
After execution, the call stack is empty.
-
Repeat the execution of tasks in the micro task queue, then execute tasks in the macro task queue.
Key points:
-
All tasks in the micro task queue will be executed in sequence until the queue length is empty.
-
The macro task queue only takes one task from the queue for execution at a time, and after execution, it goes to execute tasks in the micro task queue.
026 How to improve the first screen loading speed?#
-
Compress the code to reduce code size.
-
Route lazy loading.
-
Introduce third-party libraries via CDN to reduce code size, thereby improving first screen loading speed.
-
SSR (Server-Side Rendering).
027 What are symmetric and asymmetric encryption?#
Symmetric encryption uses the same key for both encryption and decryption, and the system's confidentiality mainly depends on the security of the key, regardless of whether the algorithm is secret.
Asymmetric encryption uses a public key for encryption and a private key for decryption. Using asymmetric encryption can enhance the security of communication.
Common symmetric encryption algorithms include: DES, AES.
Asymmetric encryption algorithm: RSA.
Is hash considered encryption? No, hash is irreversible; encryption should allow data to be restored from the encrypted data.
028 What is the difference between loader and plugin in webpack?#
Loader is a converter that compiles file A into file B, for example, converting A.less to A.css, a pure file conversion process.
Plugin is an extender that enriches webpack itself, targeting the entire process after the loader ends. It does not directly operate on files but works based on an event mechanism, listening for certain nodes in the webpack packaging process to perform extensive tasks.
029 What does flex: 0 1 auto mean in a flexbox, and what are the widths of the left and right boxes?#
The three parameters correspond to flex-grow, flex-shrink, and flex-basis, with default values of 0 1 auto.
-
The flex-grow property defines the scaling ratio of the item, defaulting to 0, meaning it will not grow if there is remaining space.
-
The flex-shrink property defines the shrinking ratio of the item, defaulting to 1, meaning if space is insufficient, the item will shrink.
-
The flex-basis property defines the space occupied by the item on the main axis before allocating excess space.
Question 1, examining flex-shrink: Find the final widths of left and right.
<div class="container">
<div class="left"></div>
<div class="right"></div>
</div>
<style>
* {
padding: 0;
margin: 0;
}
.container {
width: 600px;
height: 300px;
display: flex;
}
.left {
flex: 1 2 500px;
background: red;
}
.right {
flex: 2 1 400px;
background: blue;
}
</style>
Corresponding to the question:
-
The overflow width of the child items is:
500 + 400 - 600 = 300
. -
Left shrink ratio:
(500 * 2) / (500 * 2 + 400 * 1) = 0.7143
. -
Right shrink ratio:
(400 * 1) / (500 * 2 + 400 * 1) = 0.2857
.
Correspondingly:
-
Left shrink width:
0.7143 * 300 = 214.29
. -
Right shrink width:
0.2857 * 300 = 85.71
.
So:
-
Left final width:
500 - 214.29 = 285.71
. -
Right final width:
400 - 85.71 = 314.29
.
Question 2, examining flex-grow: Find the widths of left and right.
<div class="container">
<div class="left"></div>
<div class="right"></div>
</div>
<style>
* {
padding: 0;
margin: 0;
}
.container {
width: 600px;
height: 300px;
display: flex;
}
.left {
flex: 1 2 300px;
background: red;
}
.right {
flex: 2 1 200px;
background: blue;
}
</style>
Remaining space: 600 - (300 + 200) = 100
.
The flex-grow values of the child elements are 1 and 2, respectively, so the remaining space is divided into 3 parts: 100 / 3 = 33.3333333
.
So:
-
Left final width:
300 + 1 * 33.33 = 333.33
. -
Right final width:
200 + 2 * 33.33 = 266.67
.
Extension: What does flex: 1
represent? It is equivalent to flex: 1 1 0%
.
030 What are the differences between require and import?#
-
Import is an ES6 syntax standard, while require is an AMD specification import method.
-
Import is loaded during code compilation, so it must be placed at the beginning of the file, while require is loaded during code execution, so it can theoretically be used anywhere in the code, making import perform better.
-
When the object imported by import is modified, the source object is also modified, which is equivalent to a shallow copy; when the object imported by require is modified, the source object is not modified, which is referred to as a value copy and can be understood as a deep copy.
-
Import is conducive to tree-shaking (removing unused code in the JavaScript context), while require is not friendly to tree-shaking.
-
Import triggers code splitting (separating code into different bundles that can be loaded on demand or in parallel), while require does not trigger it.
Currently, all engines have not yet implemented import; import will ultimately be transpiled to require. In webpack packaging, both import and require will become webpack_require.
031 What are the six new features of HTML5?#
-
Semantic tags, such as header, footer, section, article, etc. The role of semantic tags: enhance the readability of the page (enhanced structure), more favorable for SEO, and more friendly for users using screen readers.
-
New media elements, audio and video tags can easily output audio or video streams, providing convenient APIs for obtaining file information.
-
The canvas attribute for drawing. The Canvas API provides a way to draw graphics using JavaScript and the HTML canvas element. It can be used for animation, game graphics, data visualization, image editing, and real-time video processing.
-
New local storage methods: sessionStorage, localStorage. sessionStorage is used to store session-level data, which disappears when the session ends and cannot have an expiration time set. localStorage is used to store data that needs to be persisted; as long as it is not actively deleted, the data will not disappear.
-
New technologies: webworker, websocket. webworker: for multi-threaded programming, websocket: a protocol for bidirectional data communication between client and server.
-
New form controls: calendar, date, time, email, url, search.
032 What are the new features of CSS3?#
-
Selectors.
-
Borders and rounded corners.
-
Backgrounds and gradients.
-
Transitions.
-
Transformations.
-
Animations.
033 What are the new features of ES6?#
-
Variable declarations: const and let.
-
Template strings.
-
Arrow functions.
-
Default parameter values for functions.
-
Spread operator.
-
Object and array destructuring.
-
Data type Symbol.
-
Data structures Set and Map.
-
Proxy and Reflect.
-
Promise objects.
-
Iterator.
-
Generator functions.
-
Async/Await.
-
Class inheritance.
-
Module syntax import/export.
034 What are the ways to merge objects?#
-
Spread operator:
const newObj = { ...obj1, ...obj2 };
-
Object.assign()
:const newObj = Object.assign(obj1, obj2);
Difference: The spread operator returns a new object, while Object.assign()
modifies its first passed object.
035 What are e.target and e.currentTarget?#
e.target refers to the object that triggered the event, which is the element that triggered the event.
e.currentTarget refers to the element to which the event is bound.
036 What is the difference between arrow functions and regular functions (function)? Can constructor functions (function) use new to create instances, and can arrow functions? Why?#
Arrow functions differ from regular functions in the following ways:
-
The this object inside the function body is the object where it is defined, not where it is used.
-
Cannot use the arguments object, which does not exist in the function body. If needed, rest parameters can be used instead.
-
Cannot use the yield command, so arrow functions cannot be used as Generator functions.
-
Cannot use the new command because:
-
They do not have their own this, so they cannot call call or apply.
-
They do not have a prototype property, while the new command requires assigning the constructor's prototype to the new object's proto.
037 What are the implementation principles of var, let, and const?#
The differences between var and let/const are:
-
Block scope: Variables declared with var do not have block scope and are valid in the global scope, while let/const are only valid within the code block they are in.
-
No variable hoisting: Variables defined with var can be used before declaration, while let/const can only be used after declaration.
-
Temporal dead zone: Variables declared with let/const have a temporal dead zone, meaning as long as there is a block scope, the declared variables are bound to that area and are no longer affected by the outside.
-
No duplicate declarations: let/const do not allow the same variable to be declared multiple times in the same scope.
-
Global variables declared with let/const will not hang on the top-level object.
const:
-
Must be assigned a value immediately after declaration, or it will throw an error.
-
For simple types, const cannot be changed once declared; for complex types (arrays, objects, etc.), the pointer address cannot be changed, but the internal data can be modified.
Let is generally used to declare variables, while const declares constants.
038 How to design and implement seamless carousel?#
Basic plugins can achieve infinite carousel, but to implement seamless scrolling with native code, I can provide some ideas, as carousels are generally inside a ul box with li elements.
-
First, get the first li element and the last li element.
-
Clone the first li element and the last li element.
-
Insert them after the last li and before the first li, respectively.
-
Then listen for the scroll event; if the scroll distance exceeds x or -x, let it jump to the next image or the previous image (it’s best to set a scroll distance here).
-
Then, achieve seamless transition between the last image and the cloned first image when scrolling to the last image; when stopping at the cloned first image, let it switch to the real first image, thus achieving infinite scrolling, and the same applies for scrolling forward.
039 What is the implementation idea of converting ES6 code to ES5 code?#
The conversion of ES6 code to ES5 code can refer to Babel's implementation method. So how does Babel convert ES6 to ES5? It can be roughly divided into three steps:
-
Parse the code string into an abstract syntax tree, known as AST.
-
Process the AST; during this stage, ES6 code can be converted to ES5 code.
-
Generate the code string based on the processed AST.
040 What are the methods to change the context of this and their differences?#
Three methods: call, apply, bind.
The difference between call and apply: they accept different parameters; both call and apply's first parameter is the context (this) for the function execution, while call passes subsequent parameters individually, and apply's second parameter is an array of parameters.
The difference between bind and call/apply: bind returns a function, while call and apply invoke immediately.
041 How to solve the 1px pixel problem on mobile Retina screens?#
-
Pseudo-elements + transform scaleY(.5).
-
border-image.
-
background-image.
-
box-shadow.
042 What is the time difference between accessing the first element and the 100,000th element in an array containing 100,000 data points?#
Arrays can directly access the corresponding elements based on their index, so the time complexity for accessing any position is O(1).
Conclusion: The time consumption is almost the same, and the difference can be ignored.
043 What is the difference between for in and for of?#
Both can be used for iteration, but for in iterates over the array's indices (index), while for of iterates over the array's element values (value).
For in is more suitable for iterating over objects; it can also iterate over arrays but may have some issues, such as:
-
The index is a string-type number, which cannot be directly used for geometric operations.
-
The iteration order may not follow the actual internal order of the array.
-
Using for in will iterate over all enumerable properties of the array, including those from the prototype. If you do not want to iterate over prototype methods and properties, you can check inside the loop using the hasOwnProperty() method to determine whether a property is an instance property of that object.
for (let index in arr) {
if (arr.hasOwnProperty(index)) {
}
}
For of iterates over the array's element values, and it only iterates over the elements within the array, excluding prototype properties and indices.
Summary:
-
For in iterates over the array's indices (keys), while for of iterates over the array's element values.
-
For in always gets the keys of objects or the indices of arrays/strings.
-
For of always gets the values of objects or the values of arrays/strings.
044 What is a closure? What should be noted when using closures?#
In JavaScript, functions can directly read global variables, but cannot read local variables from outside the function. A closure is a function that has the right to access variables in another function's scope, meaning it can read variables from other functions.
What should be noted when using closures?
-
Code maintenance difficulty: Closures can access and change private variables in the upper scope, so caution should be exercised to avoid arbitrarily changing the values of private variables in the upper scope.
-
Memory leaks: Since closures keep all variables in memory, they can consume a lot of memory, so closures should not be overused; memory that is no longer needed should be released in a timely manner to avoid memory leaks.
-
this context: The this context of a closure points to the window.
Closure application scenarios: callbacks, IIFE, function debouncing, throttling, currying, modularization.
045 What are the differences between the <Link>
tag and the <a>
tag in react-router?#
From the final rendered DOM perspective, both are links and are <a>
tags. The difference is:
-
<Link>
is a link for routing jumps implemented in react-router, usually used in conjunction with<Route>
. React-router takes over its default link jump behavior, which differs from traditional page jumps. The "jump" behavior of<Link>
will only trigger the corresponding page content update of the matching<Route>
, without refreshing the entire page. -
The
<a>
tag is a regular hyperlink used to jump from the current page to another page pointed to by href (non-anchor case).
046 How to implement lazy loading?#
Route lazy loading: For SPA (Single Page Applications) like React/Vue, when packaging the application, the JS bundle can become very large, affecting page loading. Route lazy loading can split the components corresponding to different routes into different code chunks, which are only loaded when the route is accessed, making it more efficient.
Implementation of Vue route lazy loading:
For Vue, Vue Router supports dynamic imports, which can replace static imports.
// import UserDetails from './views/UserDetails'
// Replace with
const UserDetails = () => import('./views/UserDetails')
To group components, sometimes you may want to package all components under a certain route into the same asynchronous chunk (chunk). You can use named chunks, a special comment syntax to provide the chunk name (requires Webpack > 2.4). Webpack will group any asynchronous module with the same chunk name into the same asynchronous chunk.
const UserDetails = () => import(/* webpackChunkName: "group-user" */ './UserDetails.vue')
const UserDashboard = () => import(/* webpackChunkName: "group-user" */ './UserDashboard.vue')
const UserProfileEdit = () => import(/* webpackChunkName: "group-user" */ './UserProfileEdit.vue')
React route lazy loading:
-
Implement dynamic loading of components using
React.lazy() + Suspense
. -
Use
import()
for code splitting.
047 What is MVVM?#
MVVM stands for Model-View-ViewModel, which evolves the Controller in MVC into ViewModel. The Model layer represents the data model, the View represents UI components, and the ViewModel serves as a bridge between the View and Model layers, binding data to the ViewModel layer and automatically rendering the data to the page. When the view changes, it notifies the ViewModel layer to update the data.
048 What is the execution order of lifecycle hooks between parent and child components in Vue?#
-
Loading and rendering process: parent beforeCreate -> parent created -> parent beforeMount -> child beforeCreate -> child created -> child beforeMount -> child mounted -> parent mounted.
-
Child component update process: parent beforeUpdate -> child beforeUpdate -> child updated -> parent updated.
-
Parent component update process: parent beforeUpdate -> parent updated.
-
Destruction process: parent beforeDestroy -> child beforeDestroy -> child destroyed -> parent destroyed.
049 Why can't mutations in Vuex and reducers in Redux perform asynchronous operations?#
Because the functions that change the state must be pure functions, pure functions always produce the same output for the same input and have no side effects. If they are asynchronous, they will introduce additional side effects, making the changed state unpredictable.
Asynchronous operations are unpredictable in terms of success or failure, and when to perform asynchronous operations is also unpredictable. If asynchronous operations succeed or fail without committing (mutation) or dispatching (action), Vuex and Redux cannot capture the results of the asynchronous operations to perform corresponding actions.
Extension: Why does Redux design reducers as pure functions?
Answer: Pure functions always produce the same output for the same input and have no side effects. The design philosophy of Redux is to avoid side effects, making the state changes retraceable, so Redux is full of pure functions.
050 In Vue, why can't child components modify Props passed from parent components?#
To ensure unidirectional data flow, making it easier to track data and avoid data confusion.
051 Does two-way binding conflict with Vuex?#
In strict mode, when using Vuex, when a user inputs data, v-model will try to directly modify the property value, but this modification is not made in the mutation, so an error will be thrown. When needing to use state from Vuex in a component, there are two solutions:
-
Bind value (state from Vuex) in the input, then listen for the change or input event, and call the mutation to modify the state value in the event callback.
-
Use computed properties with setters for two-way binding.
<input v-model="message" />
computed: {
message: {
get () {
return this.$store.state.obj.message
},
set (value) {
this.$store.dispatch('updateMessage', value);
}
}
}
mutations: {
UPDATE_MESSAGE (state, v) {
state.obj.message = v;
}
}
actions: {
update_message ({ commit }, v) {
commit('UPDATE_MESSAGE', v);
}
}
052 What are the shortcomings of Object.defineProperty in Vue's reactivity principle? Why did Vue 3.0 adopt Proxy and abandon Object.defineProperty?#
-
Object.defineProperty cannot monitor changes to array indices, leading to the inability to respond in real-time when adding elements via array indices.
-
Object.defineProperty can only hijack object properties, requiring traversal of each object and property. If the property value is an object, deep traversal is needed. Proxy can hijack the entire object and return a new object.
-
Proxy can hijack not only objects but also arrays and dynamically added properties.
053 How is computed implemented in Vue?#
Computed properties are proxied to the component instance, so when reading computed properties, an internal getter is executed rather than the user-defined method.
Computed internally implements a lazy watcher that does not evaluate upon instantiation; it marks whether the computed property needs to be re-evaluated with a dirty property. When any state that computed depends on changes, it notifies this lazy watcher to set the dirty property to true. Therefore, when reading this computed property again, it will re-evaluate.
Lazy watchers/computed properties do not evaluate upon creation but evaluate when used.
054 What are the differences between computed and watch in Vue?#
Computed: Computed properties are new values derived from known values in data. This new value only changes based on the changes of known values; changes in unrelated data do not affect this new value. Computed properties are not in data. Others' changes affect me.
Watch: Watchers listen for changes in data; the data being listened to is known values in data, and my changes affect others.
-
Watch is good for scenarios where one data affects multiple data.
-
Computed is good for scenarios where one data is affected by multiple data.
055 What are the principles of v-if, v-show, and v-html, and how are they encapsulated?#
-
v-if calls the addIfCondition method, ignoring the corresponding node when generating the vnode, so it will not render during the render phase.
-
v-show generates a vnode, and during the render phase, it will also render as a real node, but will modify the show property value (i.e., display) in the node's attributes during the render process.
-
v-html first removes all nodes under the node, calls the html method, and adds the innerHTML property through addProp; ultimately, it sets innerHTML to the value of v-html.
056 What are the similarities and differences between v-show and v-if directives?#
Similarities: Both can control the visibility of elements.
Differences: The essence of their implementation methods is different. v-show essentially controls the display property in CSS, setting it to none to control hiding, and only compiles once; v-if dynamically adds or removes DOM elements from the DOM tree. If the initial value is false, it will not compile, and v-if continuously destroys and creates, which is relatively performance-consuming.
Summary: If frequent switching of a node is needed, use v-show (switching overhead is relatively small, initial overhead is larger). If frequent switching of a node is not needed, use v-if (initial rendering overhead is relatively small, switching overhead is larger).
057 What are the communication methods between Vue components?#
-
Parent-child communication: Parent passes data to child via props, and child communicates back to parent via $emit; communication can also occur via $parent (parent component instance) / $children (child component instance); $ref can also access component instances; provide/inject; $attrs/$listeners.
-
Sibling communication: Event Bus, Vuex.
-
Cross-level communication: Event Bus, Vuex; provide/inject; $attrs/$listeners.
058 How to achieve communication between multiple browser tabs?#
- Use localStorage for communication.
window.addEventListener('storage', (e) => {
console.info('localStorage changed:', e)
})
- Use websocket.
The principle is simple; if pageA and pageB both establish a websocket connection with the server, both pages can receive messages sent from the server in real-time and send messages to the server in real-time. If pageA changes data, it sends a message to the server, which then sends this message to pageB, thus achieving simple communication between the two tabs.
- Use SharedWorker.
SharedWorker is a type of web worker that can be shared by all same-origin pages. Utilizing this feature allows it to be used for communication between multiple tabs.
Its implementation is similar to that of websocket, involving sending and receiving data. SharedWorker acts like a websocket server.
// worker.js
const set = new Set()
onconnect = (event) => {
const port = event.ports[0]
set.add(port)
// Receive messages
port.onmessage = (e) => {
// Broadcast messages
set.forEach((p) => {
p.postMessage(e.data)
})
}
// Send messages
port.postMessage('worker broadcasting message')
}
// pageA
const worker = new SharedWorker('./worker.js')
worker.port.onmessage = (e) => {
console.info('pageA received message', e.data)
}
// pageB
const worker = new SharedWorker('./worker.js')
worker.port.postMessage(`Client B sent message: HELLO`)
- Use cookie + setInterval.
The principle is to continuously poll the cookie in the page that needs to receive messages, while the page sending messages stores data in the cookie, thus achieving simple data sharing.
setInterval(() => {
// Add a timer to call the function every second to achieve page refresh
console.log('cookie', document.cookie)
}, 1000)
059 What is the principle of event delegation and its advantages and disadvantages?#
What is event delegation: Since events propagate to parent nodes during the bubbling phase, the event listeners for child nodes can be handled uniformly. By specifying an event handler, one can manage all events of a certain type, which is called event delegation.
Principle: Utilizing the event bubbling mechanism.
Advantages:
-
Can save a lot of memory by reducing event registrations.
-
Can implement adding and removing events for newly added child objects without needing to bind events to them again, which is particularly suitable for dynamic content.
Disadvantages:
-
Event delegation relies on bubbling, so events that do not support bubbling are not suitable for event delegation.
-
Not all event bindings are suitable for event delegation; improper use may lead to unnecessary elements also being bound to events.
060 In Vue, is it necessary to use event delegation when binding events to each item in v-for? Why?#
First, we need to know what the main functions of event delegation are:
-
Event delegation can avoid the need to add and remove events for each element individually.
-
Event delegation performs better than binding an event to every single element.
From Vue's perspective, the above two points:
-
In v-for, we can directly use a for loop to bind events to each element in the template, and when the component is destroyed, Vue will automatically remove all event handlers for us. Therefore, Vue has already accomplished what event delegation can do.
-
In v-for, the events bound to elements are all the same, so unless there are thousands of elements needing events, the performance difference is not significant, so there is no need to use event delegation.
061 What are the advantages and disadvantages of Proxy compared to Object.defineProperty?#
-
Proxy can directly listen to objects rather than properties.
-
Proxy can directly listen to changes in arrays.
-
Proxy has up to 13 interception methods, including apply, ownKeys, deleteProperty, has, etc., which Object.defineProperty does not have.
-
Proxy returns a new object, allowing us to operate on the new object to achieve our goals, while Object.defineProperty can only directly modify the properties of the object.
-
As a new standard, Proxy will receive continuous performance optimizations from browser vendors, which is the so-called performance dividend of new standards.
-
Object.defineProperty is compatible with IE.
062 How does Vue achieve two-way data binding?#
Vue achieves two-way binding based on data hijacking. Vue 2.0 uses Object.defineProperty, while Vue 3.0 uses the newly added Proxy in ES6.
What is data hijacking: It involves hijacking the accessors of an object using Object.defineProperty, allowing us to detect changes when property values change, enabling further operations.
Advantages of data hijacking:
-
No need for explicit calls: For example, Vue uses data hijacking + publish-subscribe to directly notify changes and drive view updates.
-
Precise knowledge of changed data: By hijacking the setter of properties, when property values change, we can precisely know what has changed.
The implementation idea of two-way binding based on data hijacking:
-
Use Proxy or Object.defineProperty to create an Observer that "hijacks" the object/object properties, notifying subscribers when properties change.
-
The parser Compile parses the directives in the template, collecting the methods and data that the directives depend on, waiting for data changes to render.
-
Watcher serves as a bridge between Observer and Compile, receiving data changes generated by Observer and rendering the view according to the directives provided by Compile, ensuring that data changes prompt view changes.
063 In Vue's two-way data binding, how does the Model change the View, and how does the View change the Model?#
The process of the Model changing the View relies on ES5's Object.defineProperty, which achieves data hijacking through defineProperty. The getter collects dependencies, and the setter calls the update callback.
The process of the View changing the Model relies on v-model, which is a syntactic sugar that adds event listeners and assigns values to the corresponding Model based on unidirectional data binding.
064 How to optimize Vue when rendering a large amount of data?#
-
Use virtual lists.
-
For fixed non-reactive data, freeze the object using Object.freeze.
-
Utilize server-side rendering (SSR) to render components on the server.
065 How to make CSS only work in the current component in Vue?#
Add scoped in front of the style in the component.
066 What is the purpose of keep-alive?#
keep-alive is a built-in Vue component that allows the contained components to retain their state or avoid re-rendering.
067 What is vue-loader? What are its uses?#
A loader for vue files that converts template/js/style into js modules.
Uses: JS can be written in ES6, styles can be in scss or less, and templates can use jade, etc.
068 Can v-on listen to multiple methods?#
Yes, for example:
<input type="text" v-on="{ input:onInput, focus:onFocus, blur:onBlur }">
069 Why must data in Vue components be a function?#
In components, data must exist as a function and cannot be an object. When data in a component is written as a function, the data is defined as the return value of the function, ensuring that each time the component is reused, a new data instance is returned, meaning each component instance has its own private data space, responsible for maintaining its own data without causing confusion. If written as an object, all component instances share the same data, leading to changes in one affecting all.
070 What is the priority of v-if and v-for?#
When v-if and v-for are used together, v-for has a higher priority than v-if, meaning v-if will run separately for each v-for loop. Therefore, it is not recommended to use v-if and v-for together. If v-if and v-for are used together, Vue will automatically prompt that v-if should be placed outside.
071 What is the solution when events registered on router-link in Vue are ineffective?#
Use @click.native
. Reason: router-link prevents the click event, and .native
listens directly to a native event.
072 What is the difference between params and query?#
Usage: query must be introduced using path, while params must be introduced using name; receiving parameters is similar. query displays parameters in the browser address bar, while params do not.
Note: query data will not be lost on refresh, while params data will be lost on refresh.
073 What are the properties of Vuex?#
Five properties: State, Getter, Mutation, Action, Module.
state => Basic data (data source storage).
getters => Data derived from basic data.
mutations => Methods for committing changes to data, synchronous!
actions => Serve as decorators, wrapping mutations to allow for asynchronous operations.
modules => Modular Vuex.
074 What are the route navigation guards?#
Global: beforeEach, beforeResolve, afterEach.
Route-specific: beforeEnter.
Component-level: beforeRouteEnter, beforeRouteUpdate, beforeRouteLeave.
075 What are the event modifiers in Vue and their functions?#
-
.stop
: Equivalent toevent.stopPropagation()
, prevents event bubbling. -
.prevent
: Equivalent toevent.preventDefault()
, prevents the default behavior from executing. -
.capture
: When the element bubbles, it triggers the element with this modifier first. -
.self
: Only triggers events within its own scope, excluding child elements. -
.once
: Only triggers once.