The problem the forerunner

  • What’s the use of the head tag? Which of these tags is essential? [HTML]
  • Understanding of Media Query [CSS]
  • Understanding of CSS Engineering
  • Say something about the Reflect object
  • Say something about Generator objects
  • What is the difference between a single page app and a multi-page app?
  • Vue template to render
  • Does the view execute the render immediately after the data property value is updated in the Vue instance?
  • Handwritten shallow copy
  • Handwritten deep copy
  • Output result (Promise related)
  • Circular list [algorithm]

Knowledge comb

What is the use of the head tag, and what tag is essential?

The HTML HEAD element specifies configuration information (metadata) about the document, including the title of the document, referenced document styles, scripts, and so on.

Understanding of media queries?

Media Queries are a method introduced by the CSS3. The CSS takes effect only when the device environment matches the specified Media rules. In this way, you can create different CSS styles for different types of devices to achieve responsive effect.

The simplest media query looks like this:

@media media-type and (media-feature-rule) {
  /* CSS rules go here */
}
Copy the code

In addition to the @media notation, you can use the media= attribute to specify specific media types for elements like style, link, source, and so on.

<link rel="stylesheet" media="(max-width: 800px)" href="example.css" /> 
Copy the code

It consists of the following parts:

  • aThe media typeTell the browser what type of media the code is used for (such as print or screen); The following media types are available:
    • All (All equipment)
    • Print (Paged material and documents viewed on screen in Print Preview mode)
    • Screen (used chiefly on a screen)
    • Speech (mainly used in speech synthesizers)
  • aMedia expressionIs a rule or test required for the included CSS to take effect. Such aswidthIs the width of the viewport, including the width of the vertical scroll bar.
  • A set of CSS rules that are applied when the test passes and the media type is correct.

Note: Elastic boxes, grids, and multi-column layouts all give you a way to build scalable and even responsive components without media queries. It’s always worth considering whether these layouts can achieve the design you want without engaging media queries.

Reference:

  • Media Query Guide

  • Using media query

What is your understanding of CSS engineering?

And JS engineering, when the CSS scale to a certain extent, CSS engineering is also very necessary, CSS organization, design and optimization problems need more professional library to help us.

Generally speaking, THE CSS is engineered to solve the following problems:

  1. Macro design: How is the CSS code organized, broken down, and structured?
  2. Programming optimization: Make CSS rules better
  3. Automated builds: Automatic packaging
  4. maintainability

The following three directions are popular CSS engineering practices:

  • Preprocessors: LESS, SASS, etc. Using the unique syntax of CSS preprocessor, CSS editing is more logical and easier to read, which solves the problem of CSS engineering macro design.

    Preprocessors generally have the following features:

    • The ability to nest code to reflect hierarchical relationships between different CSS properties;
    • Support for defining CSS variables;
    • Provide calculation functions;
    • Allow extend and mixin for code snippets;
    • Support the use of loop statements;
    • Supports modularization of CSS files for reuse.
  • Postprocessor: PostCss, etc., according to the RULES of CSS generation is to recompile the CSS to make it better. At present, the most common thing to do is to add browser private prefix to CSS attributes to achieve cross-browser compatibility, and a bit of the feeling of using babel.js to transform JS.

  • Webpack loader and other loaders: CsS-loader and style-loader of Webpack can dynamically load CSS into a page like a plug-in, which solves the problem of automatic packaging

Say something about the Reflect object

Reflect is a built-in object that provides methods to intercept JavaScript operations. These methods are the same as the proxy Handlers method. Reflect is not a function object, so it is not constructible.

Reflect stands for reflection. We know that a Proxy can implement an object’s Proxy and also intercept its basic operations. In fact, there is nothing special about this object, we can think of it as a static utility class, a utility class that collects object interception operations.

Such as:

  • Reflect.applyIs equivalent toFunction.proptype.apply
  • Reflect.constuctorIs equivalent tonewThe operator

And so on.

Say something about Generator objects

The generator object is returned by a generator function and conforms to both the iterable and iterator protocols.

A generator object is the return value of a generator function. A function with an * is a generator function, and yields data in a fixed order using the yield operator:

function* gen() {
  yield 1;
  yield 2;
  yield 3;
}

let g = gen(); // "Generator { }"
Copy the code
  • Generator.prototype.next(): Returns a byyieldThe value generated by the expression

Take an example of an infinite iterator:

function* idMaker(){
    let index = 0;
    while(true)
        yield index++;
}

let gen = idMaker(); // "Generator { }"

console.log(gen.next().value);
/ / 0
console.log(gen.next().value);
/ / 1
console.log(gen.next().value);
/ / 2
// ...
Copy the code

Generator objects are the basis of async/await syntactic sugar. Read more about this: Async and await: Making asynchronous programming easier.

Vue the difference between a single page application and a multi-page application

  • SPA SinglePage Web Application refers to an Application that has only one main page and only needs to load js, CSS and other related resources once at the beginning. All content is contained in the main page, componentized for each functional module. Single-page application jumps, which switch related components and refresh only local resources.

  • MPA MultiPage Application refers to an Application that has multiple independent pages. Each page must repeatedly load RELATED resources such as JS and CSS. When a multi-page application jumps, the whole page resource needs to be refreshed.

Compare the item Multi-page application mode MPA Single page application pattern SPA
Application form It consists of multiple complete pages A shell page and a number of page fragments
Jump way A jump between pages is a jump from one page to another A jump between page fragments deletes or hides one page fragment, loads another and displays it. This is a simulated jump between fragments, with no open shell pages
Whether public resources are reloaded after the jump is no
URL patterns http://xxx/page1.html http://xxx/page1.html http://xxx/shell.html#page1 http://xxx/shell.html#page2
The user experience Switching between pages is slow and not smooth, and the user experience is poor, especially on mobile devices Switching between page fragments is fast and the user experience is good, including on mobile devices
Can realize transition animation Unable to realize Easy to implement (mobile app dynamic effect)
Data is passed between pages Rely on URL, cookie or localstorage, implementation trouble Because within a page, passing data between pages is easy
Search Engine Optimization (SEO) You can just do it It needs to be done separately, which is a bit troublesome
Scope of special application Need a search engine friendly site Applications with high experience requirements, especially mobile applications
Search Engine Optimization (SEO) You can just do it It needs to be done separately, which is a bit troublesome
The development of the difficulty Lower, easier frame selection A higher level requires a specialized framework to make this pattern easier to develop

For more details:

  • Advantages and disadvantages of vUE single page application and multi-page application

Vue Tempalte to render process

Simply put, the three core parts of Vue are: Compiler, ReActivity and Runtime.

  • Compiler: Indicates that the template is compiled into a regular data structure, the AST abstract syntax tree.

  • Reactivity (Data Response) : Indicates that data data can be monitored, via object.defineProperty or proxy syntax.

  • Runtime represents runtime functions, such as virtual DOM(VNode), DIff algorithm, and real DOM operations.

The render function is usually used to render the view, we can write it manually, we can refer to the runtime runtime part of the code, Saves compiling the Template into render function, which takes up a lot of memory.

The main compilation process of compiler is as follows:

  1. Convert template templates to ast (Abstract syntax tree) : THE AST stores template information more logically for later collation operations
  2. throughoptimizeFunction ofStatic nodes are optimized, give it a flag and optimize it for later updates by skipping the static nodes. Static nodes mean that this part of the DOM is not responsive and will not be updated, so there is no need for listening and detection to optimize the update efficiency.
  3. Generate render stringThrough:generateThe function generates the Render string and places the static part in staticRenderFns, which passesnew Function(render)Generate the render function.

Note: The render function is used to generate virtual nodes, which are optimized for frequently updating the DOM. AST is used in Compiler to compile templates into regular data structures, which can be easily converted into the render function. The virtual node VNode is designed to optimize DOM operations to reduce frequent DOM operations and improve DOM performance.

Does the view perform rerendering synchronously immediately after a property value in the Vue instance data changes?

Rerendering is not performed immediately and synchronously. Vue updates the DOM responsively but not immediately, but asynchronously, and updates according to a strategy for optimal rendering: **Vue opens a queue and buffers all data changes that occur in the same event loop. ** This is useful for frequent operations such as watcher data monitoring. When the same Watcher is triggered multiple times in a short period of time, these changes will be reloaded in the buffer queue, avoiding unnecessary calculations.

Implementing shallow copy

There are some off-the-shelf apis for shallow copying:

  • Object.assign()
  • Object.create() is also a shallow copy and works the same waynewKeyword consistency
  • Extended operators work the same wayObject.assign
  • An array ofsliceAnd other methods are shallow copies

Handwritten shallow copy:

function shallowCopy(obj) {
    if(! obj ||typeofobj ! ='object') {
        return {};
    }
    let newObject = Array.isArray(obj) ? [] : {};
    for (let key in obj) {
        if(obj.hasOwnProperty(key)) { newObject[key] = obj[key]; }}return newObject;
}
Copy the code

Shallow copy refers to reusing the reference of the original reference type instead of creating a new copy of data. Therefore, when the original data is changed, all references are changed. This is a shallow copy.

Implementing deep copy

  • useJSON.parse(JSON.stringify(obj))One of the most common deep-copy methods is using serialization and deserialization of JSON to create a new object. There are some limitations to this approach, however, that objects that json does not support serialization will disappear, such as functions, custom objects, and so on.
  • uselodashThe librarycloneDeepmethods

Here is the implementation of deep copy by hand:

function deepCopy(obj) {
    if(! obj ||typeofobj ! ='object') {
        return {};
    }
    let newObject = Array.isArray(obj) ? [] : {};
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObject[key] = obj[key] && typeof obj[key] === 'object'? deepCopy(obj[key]) : obj[key]; }}return newObject;
}
Copy the code

In fact, the difference from shallow copy is that it expands the copy as it encounters the object, rather than assigning the reference directly, so that deep copy can be implemented.

We’re also going to assign functions directly, so normally for functions of this type we’re not going to change them.

Output results (Promise related)

Code snippet:

function runAsync (x) {
    const p = new Promise(r= > setTimeout(() = > r(x, console.log(x)), 1000))
    return p
}

Promise.all([runAsync(1), runAsync(2), runAsync(3)]).then(res= > console.log(res))
Copy the code

A. all B. all C. all D. all The promise. all function executes all asynchronous functions in parallel, outputs an array of state values for all promises in the same order of argument iteration if they succeed, and returns the failed Promise if one fails.

So the output is obvious:

1
2
3
[1, 2, 3]
Copy the code

Code snippet:

function runAsync (x) {
  const p = new Promise(r= > setTimeout(() = > r(x, console.log(x)), 1000))
  return p
}
function runReject (x) {
  const p = new Promise((res, rej) = > setTimeout(() = > rej(`Error: ${x}`.console.log(x)), 1000 * x))
  return p
}
Promise.all([runAsync(1), runReject(4), runAsync(3), runReject(2)])
       .then(res= > console.log(res))
       .catch(err= > console.log(err))
Copy the code

Since the execution is parallel, the asynchronous execution time determines which asynchronous execution finishes first.

  1. RunAsync (1) executes, triggering the setTimeout async callback 1s later, printing 1 with a status of success
  2. RunReject (4) Execute. After 4s, setTimeout is triggered. 4 is printed, and the status fails
  3. RunAsync (31) executes, triggering the setTimeout asynchronous callback 1s later, printing 3 with the status as success
  4. RunReject (2) is executed, the setTimeout async callback is triggered after 2s, 2 is printed, the status fails, promise. all catches an error, and the catch callback is executed asynchronously

Note the order in which callbacks are triggered:

// 1s
1
3
// 2s
2
Error: 2
// 4s
4
Copy the code

Circular linked list

Given a linked list, determine whether there are rings in the list. If there is a node in the list that can be reached again by following the next pointer continuously, then there is a ring in the list. /** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; *} * /Copy the code

The problem is very simple, is traversed the list, determine whether the list points to the traversed node can be.

/ * * *@param {ListNode} head
 * @return {boolean}* /
var hasCycle = function(head) {
    const node_caches = [];
    let next = head;
    while(next) {
        if(node_caches.includes(next)) {
            return true;
        }
        node_caches.push(next);
        next = next.next;
    }
    return false;
};
Copy the code

This idea is advantageous for the comparison of the front of the loop, which can end the loop. However, if the position is changed to the back, the cache space of the node will undoubtedly become larger and larger.

Subject also has a special way of thinking, that is, how quickly set pointer, every time we make slow pointer before further, and pointer step forward two steps or more quickly, so, if there are any ring, speed pointer will start “circle”, due to the fast pointer is faster than slow pointer, pointer always catch up with the slower, if none of the traverse end quick pointer meet with slow pointer, show that no ring.

/ * * *@param {ListNode} head
 * @return {boolean}* /
var hasCycle = function(head) {
    let slow = head, quick = head && head.next;
    while(quick) {
        if(slow == quick || slow == quick.next) {
            return true;
        }
        slow = slow.next;
        quick = quick.next && quick.next.next;
    }
    return false;
};
Copy the code