[TOC]

preface

I am very happy to share some small front-end problems this time, and the completed code cases will be published in the first timeweb-interview-questions

This is also the author’s hope to sort out the problems encountered in work or other scenes in the warehouse through bit by bit records. If you finish reading this article, you can click “like”

After the front-end knowledge will mostly write, hope a piece of record, a piece of learning, some refer to the front-end big guy, open source long live, thank you

Recommended reading

I suggest you take a look at these articles first

  • After I boldly modified the prop from the parent component?
  • An unfinished summary of browser rendering
  • [the interviewer] | or say, the new operator in JavaScript (don’t go)

This share of front-end related small knowledge points: the whole is divided into six categories

  • Front-end browser related

Q1: How do browsers render? A common interview question that maps to the front end is: What happens when the user opens the browser (type in the URL) in a happy mood


  • Frame-vue correlation

Q1: In the Vue framework, why not try to change props

Q2: What does vUE do if it changes by accident

Q3: Whether the bidirectional binding of VUE conflicts with vuex

Q4: The order in which vue’s parent and child lifecycle hooks are executed


  • Native JavaScript correlation

Q1: Sort an array using sort()

Q2: Output code to see the result why

var obj = {
    '2'3.'3'4.'length'2.'splice'Array.prototype.splice,
    'push'Array.prototype.push
}
obj.push(1)
obj.push(2)
console.log(obj)


Copy the code

  • New syntax feature in ES6 – arrow functions

Q1: What is the difference between arrow functions and normal functions?

Q2: Constructors can use new to generate instances, but can arrow functions? why


  • API performance

Q1: A.B.C.D or a[‘b’][‘c’][‘d’], which performance is higher?

Q2: There are 100,000 elements in the array. How long is the difference between the first element and the 100,000th element


  • Data structure algorithm correlation

Q1: Given the data format, implement a function fn to find all the parent ids in the chain

To prepare

  • The source code of the vue
yarn add vue
Copy the code
  • A small test project

00- Given the data format, implement a function fn to find all the parent ids in the chain

There are two types of data structures that are similar to arrays,

But you have more control over adding and removing elements. These are stacks and queues

Stack LIFO

A stack is an ordered collection that follows LIFO. New elements added or to be deleted are stored at the same end of the stack, called the top, and the other end is called the bottom. In the stack, the new elements are near the top of the stack, and the old elements are near the bottom of the stack

  • Push (Element (s)) : Add a new element(or elements) to the top of the stack.

  • Pop () : Removes the element at the top of the stack and returns the removed element.

  • Peek () : Returns the element at the top of the stack without modifying the stack. (This method does not remove the top of the stack

Element, just return it.

  • IsEmpty () : Returns true if there are no elements in the stack, false otherwise.

  • Clear () : Removes all elements in the stack.

  • Size () : Returns the number of elements in the stack. This method is similar to the length property of an array.

Queue FIFO

  • Enqueue (Element (s)) : Adds one (or more) new items to the end of the queue
  • Dequeue () : removes the first item in the queue and returns the removed element
  • Front () : Returns the first element in the queue — the element that was added first and will be removed first. The queue does nothing (no element is removed, only element information is returned — very similar to the PEEK method of the Stack class)
  • IsEmpty () : Returns true if the queue contains no elements, false otherwise
  • Size () : Returns the number of elements contained in the queue, similar to the length property of an array

Breadth-first search for BFS

The breadth-first search algorithm traverses the graph starting with the first vertex specified, visiting all of its neighboring points first, like one layer of the graph at a time.

Depth-first search DFS

A depth-first search algorithm will traverse the graph from the first specified vertex, follow the path until the last vertex of the path is visited, and then backtrack and explore the next path. In other words, it accesses vertices in depth before breadth

algorithm The data structure describe
Depth-first search The stack Depth-First Search By putting vertices on the stack, vertices are explored along the path, and new adjacent vertices are accessed
Breadth-first search The queue Breadth-First Search By putting vertices in the queue the first vertices that are queued are explored first

There are two schemes:

  • The first option is to use the stack data structure

DFS, which is based on recursion, is itself a call stack. In each call stack, the current stack element is saved, and then a comparison is made according to the given value to decide whether to continue the recursive search or to interrupt the recursion. Note the recursive interrupt logic, and the preservation of each call stack element

The process is simply as deep as you can go into every possible branch path, and each node can only be accessed once

function dfs(target, id) {
  let stack = [...target];

  do {
    console.table(stack)
    const current = stack.pop();
  // console.log(current) // 2 21 212 211 1 12 121 11 112 111
    if (current.id === id) {
      return current;
    }
    if (current.children) {
      let nextNode = current.children;
      let nextNodeAddPreId = nextNode.map((item) = > ({
        ...item,
        containsThePreviousLevelId: `${ current.containsThePreviousLevelId || current.id } ${item.id}`,}));// console.log(... nextNodeAddPreId)
      stack.push(...nextNodeAddPreId);
     
    }
  } while (stack.length);
}
Copy the code
  • The second option is to use the data structure queue

01- Output the results of the following code execution and explain why

var obj = {
    '2': 3.'3': 4.'length': 2.'splice': Array.prototype.splice,
    'push': Array.prototype.push
}
obj.push(1)
obj.push(2)
console.log(obj)
Copy the code

Class (pseudo) Array (ArrayLike)

  • Objects that look like arrays (some objects look like arrays but aren’t)

  • Access elements through index attributes

  • The object with the length attribute

  • Definitions in underscore

    var MAX_ARRAY_INDEX = Math.pow(2.53) - 1;
    var getLength = property('length');
    var isArrayLike = function(collection) {
      var length = getLength(collection);
      return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; // The largest number that can be accurately represented in JavaScript
    };
    Copy the code
  • Methods without arrays (push forEach)

arrayLike.push('sex') // 01.js:20 Uncaught TypeError: arrayLike.push is not a function
Copy the code

In the form of


console.log(array[0]); // name
console.log(arrayLike[0]); // name

array[0] = "new name";
arrayLike[0] = "new name";
console.log(array[0]); // new name
console.log(arrayLike[0]); // new name
Copy the code

Indirect invocation

Array.prototype.slice.call(arrayLike, 0); // ["name", "age", "sex"] 
Copy the code

Convert to a real array

Array.from(arrayLike); 
Copy the code

An array of push

  • MDN about array push

Push method has universality. This method, when used with call() or apply(), can be applied to array-like objects. The push method uses the length attribute to decide where to start inserting a given value. If length cannot be converted to a numeric value, the index of the inserted element is 0, including if length does not exist. Length will be created when it does not exist.

The only array-like objects of the native class are Strings, although they are not suitable for this method because Strings are immutable.

vernacular

[length] = arr[length] = arr[length]

var testObj = {
  "2": 3."3": 4.length: 2.push: Array.prototype.push,
};


testObj.push(1) 
console.log(testObj) //// {2:1, 3:4, length: 3, push: ƒ}
testObj.push(2)
console.log(testObj) //{2: 1, 3: 2, length: 4, push: ƒ}
Copy the code
  • The first point is that every time you push, length goes up by 1

‘splice’: Array.prototype.splice

  • Add splice to the object
 / * * *@param {? Object} obj
     * @return {boolean}* /
    function isArrayLike(obj) {
      if(! obj ||typeofobj ! = ='object') {
        return false;
      }
      try {
        if (typeof obj.splice === 'function') {
          const len = obj.length;
          return typeof len === 'number' && (len >>> 0 === len && (len > 0 || 1 / len > 0)); }}catch (e) {
      }
      return false;
    }
Copy the code

Why does an object add the splice property and not call it become an array-like object, which is a way for DevTools in the console to guess what an array of classes is

  • Exists and is an object
  • On the objectspliceAttributes are function types
  • On the objectlengthProperty and is a positive integer

02- sort arrays with sort() – [3,15,8,29,102,22]

MDN sort

sort()Methods usingIn situ algorithmSort the elements of an array and return an array. The default sort order is built when converting elements to strings and then comparing their UTF-16 code unit value sequences

  • In situ algorithm in situ algorithm
  • Convert elements to strings
  • UTF-16

Using UTF-16, common character numbers in English upper and lower case Chinese characters

let arrs = ['Hello.'.'HELLO'.'hello'.Awesome!]
arrs.sort()
console.log(arrs)  // [666, "HELLO", "HELLO", "HELLO"]
Copy the code

conclusion

Numbers English uppercase English lowercase Chinese characters

	/**
     * Sorts an array.
     * @param compareFn Function used to determine the order of the elements. It is expected to return * a negative value if first argument is less than second argument, zero if they're equal and a positive * value otherwise. If omitted, The elements are sorted in ascending, ASCII character order. * ' 'ts * [11,2,22,1]. Sort ((a, b) => a-b) *' '*/sort(compareFn? :(a: T, b: T) = > number): this;
Copy the code
  • Ruan teacher character encoding

  • steps

    • Convert to string number > English uppercase > English lowercase > Chinese character

    • Compare the first character ===>15 102 29 22 3 8
    • Compare the second character ===>102 15 22 29 3 8
    • Compare the third character ===>102 15 22 29 3 8
  • case

arr.sort((x, y) = > {
  console.log(` sorting:${x}----${y}`);
});
Copy the code
Sorting: 15-3 sort: 8 -- 15 sorts: 29-8 sorts: 102-29 sorting: 22-102Copy the code
arr.sort((x, y) = > {
  console.log(`${x}-${y}=${x - y}`);
});
Copy the code
15 minus 3 is 12 8 minus 15 is minus 7 29 minus 8 is 21 102 minus 29 is 73 22 minus 102 is minus 80Copy the code
arr.sort((x, y) = > {
  console.log(`${x}-${y}=${x - y}`);
  return x - y;
});
console.log(arr);
Copy the code
15-3=12 8-15=-7 8-15=-7 8-3=5 29-8=21 29-15=14 102-15=87 102-29=73 22-15=7 22-102=-80 22-29=-7 [3, 8, 15, 22, 29, 102]Copy the code
  • conclusion
    • If the return value is less than 0, x moves to y in ascending order. Return x-y
    • If the return value is greater than 0, x moves to y and returns y-x in descending order
    • The return value of 0 is relatively constant in most browsers
  • Results:

[102, 15, 22, 29, 3, 8]

03- About arrow functions

Q5: What is the difference between arrow functions and ordinary functions? Constructors can use new to generate instances, but can arrow functions? Why is that?

  • MDN – Arrow function

  • Ruan es6- arrow function

What is an arrow function

  • Grammar is simple
  • Doesn’t have its own this
  • Cannot be used as a constructor.
const agesArr = [12.13.7.8 ]

const res = agesArr.map(item= >`${item}At the age of `)
console.log(res) // ['12 ', '13 ', '7 ', '8 ']
Copy the code
const fn  = ([a, b] = [1.2], {x: c} = {x: a + b}) = > a + b + c;
const res1 = fn()
console.log(res1) / / 6
Copy the code

advantage

  • Default values for parameters of a function

    • before
    function log(x, y) {
      y = y || 'World';
      console.log(x, y);
    }
    
    if (typeof y === 'undefined') {
      y = 'World';
    }
    Copy the code
    • now
    function Point(x = 0, y = 0) {
      this.x = x;
      this.y = y;
    }
    Copy the code
  • It’s shorter to write

  • There is no single this

  • The arrow function makes the presentation more concise.

No arrow function

Is a function defined in terms of how it is calledthis

  • If the function is a constructor, the this pointer points to a new object
  • In strict mode function calls, this refers to undefined
 function Person() {
        // The Person() constructor defines' this' as its own instance.
        this.age = 0;

        setInterval(function growUp() {
          console.log(this);
          // In non-strict mode, growUp() defines' this' as a global object,
          // Not the same as' this' defined in the Person() constructor.
            // This is the window object.
          this.age++;
        }, 1000);
      }
Copy the code

Use the arrow function

function Person(){
  this.age = 0;

  setInterval(() = > {
    this.age++; / / | this | to p instance correctly
  }, 1000);
}

var p = new Person();
Copy the code

Arrow functions will not create their ownThis, which inherits this only from the upper level of its scope chain

What’s the difference between a normal function and an arrow function

  • The this object inside the function is the object at which it is defined, not used
let obj = {
  name: "Zhang".sayHi() {
    console.log(this); // obj is the object
    function sayName() { 
      console.log(this); // this is a function that points to the window
    }
    sayName()
    const foo = () = >{
      console.log(this) // obj is the object
    }
    foo()
  },
};
console.log(obj.name);
obj.sayHi();

Copy the code
  • ES6 introduces the REST parameter of the form. The variable name), which is used to get extra arguments to the function so that they are not neededargumentsThe object. The rest argument goes with a variable that puts the extra arguments into an array.
The // arguments variable is written like an array of objects
function sortNumbers() {
  return Array.prototype.slice.call(arguments).sort();
}

// Rest arguments are written as real arrays
const sortNumbers = (. numbers) = > numbers.sort();
Copy the code
  • UnusableyieldCommand, so arrow functions cannot be used as Generator functions.

The new operator in JavaScript

The interview questions

Do you have a lot of question marks

  • Question1: What did New do after that?
  • Can I write the principle of the new operator?

MDN description of the new operator keyword

  1. Create an empty simple JavaScript object (i.e{});
  2. Link this object (that is, set its constructor) to another object;
  3. Take the object created in Step 1 as the objectthisContext;
  4. Returns if the function does not return an objectthis.

The above four articles are about the new operator (or keyword) on MDN. It is a simple experience to use the constructor to new an object

var self;

function Person(name) {
  console.log(this);
  self = this;
  this.name = name;
}
let p = new Person("Zhang");
console.log(p);
console.log(self === p); // This in the true constructor is bound to p
console.log(p.__proto__ === Person.prototype); // The stereotype property of object P points to the constructor stereotype, thus ensuring that the instance can access the properties and methods defined in the constructor stereotype.
Copy the code

Then add the prototype method to the constructor

function Persion(name){
    this.name = name
}
console.log(Persion.prototype)
Persion.prototype.sayHello = function(){
    console.log(this) // point to the constructed object
    console.log(this.name) / / xiao Ming
}

let xiaoMing = new Persion('Ming')
xiaoMing.sayHello()
Copy the code

As can be seen from the simple case mentioned above,

  • New A constructor returns an object whose stereotype property (that is, __ proto __) is congruent with the constructor’s stereotype

  • An instance of new created by the constructor Persion can access properties in the constructor, and that’s it

    console.log(xiaoMing.name) / / xiao Ming
    Copy the code
  • To the point: Instance objects from new are linked by a prototype chain and a constructor

A constructor is basically a function, and a function can have a return value

function Person(name) {
  this.name = name;
  // return 1; // Returns the internally created object
  // return "1"; // Returns the internally created object
  // return null; // Returns the internally created object
  // return undefined; // Returns the internally created object
  // return {}; // {} // returns directly
  return function () {}; // Return directly
  return [1]; // [1] // Returns directly
}
let p = new Person("Bill");
console.log(p);
Copy the code

Given the worthwhile idea of returning a constructor, test it out with different data types

  • Different data types return different effects, like the number 1 string “1”, which still returns an internally created object
  • So if you return an object ({}) or an array ([]), it will be returned directly

summary

That is, constructors generally do not need a return

  • Return a generic datatype. It doesn’t work
  • So let’s return an object. What’s the point of new

Write your own myNew

If you implement a new yourself, you must first satisfy several of its effects

  1. A constructor that returns an object should have an object in it

    let obj ={}
    Copy the code
  2. And points its __proto__ attribute to the constructor’s Prototype attribute

    obj.__proto__ = constructor.prototype;
    Copy the code
  3. Call the constructor to bind this

    constructor.apply(obj, args)
    Copy the code
  4. The original value should be ignored, and the returned object should be processed normally

    res instanceof Object ? res : obj
    Copy the code

The test results

function myNew() { let [constructor, ...args] = [...arguments]; let obj = {}; obj.__proto__ = constructor.prototype; let res = constructor.apply(obj, args); return res instanceof Object ? res : obj; } function Person(name) { this.name = name; // return {}; } person.prototype. sayHi = function () {console.log(' function in prototype method --${this.name} '); }; Let p1 = myNew(Person, "test "); // console.log(p1) p1.sayHi(); console.log(p1.name);Copy the code

Arrow function usingnew

 var Foo = () = > {};
      var foo = new Foo(); // TypeError: Foo is not a constructor
Copy the code
  • Cannot be used as constructors, that is, not usednewCommand, otherwise an error will be thrown

thisPointing is fixed, not because there is a binding inside the arrow functionthisThe actual reason for this is that arrow functions don’t have their ownthisLead to internalthisThat’s the outer code blockthis. Precisely because it doesn’tthis, so it cannot be used as a constructor.


04- VUE life cycle advancement

The basic flow

  • New vue creates the instance
  • Initialize the event lifecycle
  • beforeCreate
  • Initialize injection validation
  • created
  • Whether to specify el
    • No: call vm.$mount(el)
    • Yes: Specifies whether to specify template
      • No Compile HTML external to the EL as template
      • Compile template to render
  • beforeMount
  • Create vm.$el and replace el with it
  • mounted
  • Mount to complete
  • When data is modified:
    • beforeUpdate
    • updated
  • Call the vm $destroy ()
  • beforeDestroy
  • Unbind destroy subcomponent event listener
  • Destruction of the completion of
  • destroyed

Loading the rendering process

The parent component is mounted after all its children are mounted, so the parent component is mounted last.

Child component update process

Child update process (when child update affects parent) : Parent beforeUpdate-> Child beforeUpdate-> Child updated -> Parent updTED Child update process (when child update does not affect parent) : Child beforeUpdate -> Child updated

Parent component update process

The eActivated function is triggered when the view is updated. Because the keep-alive component is disabled only when the view is updated.

Parent update process (when parent affects child) : Parent beforeUpdate-> Child beforeUpdate-> Child updated -> Parent updTED Parent update process (when parent does not affect child) : Parent beforeUpdate-> Parent updated

Destruction of the process

Parent beforeDestroy-> Child beforeDestroy-> Child destroyed-> Parent destroyed

Small complement

deactivated Called when the keep-alive component is disabled.
activated Called when the keep-alive component is activated.

conclusion

The sequence of Vue parent-child component lifecycle hooks follows: from the outside in, and then from the inside out again, regardless of the level of nesting

05- Whether bidirectional binding conflicts with VUEX

 const store = new Vuex.Store({
        state: {
          obj: {
            message: "hello",}},mutations: {
          increment(state){},}});var vm = new Vue({
        el: "#app",
        store,
        data() {
          return {};
        },
        computed: {
          message() {
            return this.$store.state.obj.message;
          },

          / /... mapState({
          // message: (state) => state.obj.message,
          / /}),
        },
        methods: {
          updateMessage(e) {
            this.$store.commit("updateMessage", e.target.value); ,}}});Copy the code

vue.js:634 [Vue warn]: Computed property “message” was assigned to but it has no setter.

(found in )

  • Refer to the documentation for vUE

Arrays in 06-js

preface

Arrays, linked lists, stacks and queues are all linear lists. The structures they represent are all linear structures, and the corresponding ones are nonlinear lists, such as trees, graphs and piles, which represent nonlinear structures.

thinking

  • Why can arrays hold different types in JavaScript?
  • How are arrays stored in JavaScript?

What is an array

An Array (English: Array) is a data structure consisting of a collection of elements of the same type, allocated a contiguous chunk of memory for storage.

This is the approximate location of the JS array in memory, or

In JS engine V8 of Chrome browser, there are two storage modes for arrays. One is similar to linear structure storage in C language (in the case of continuous index values and positive integers), and the other is Hash structure storage (in the case of negative index values, sparse array and large spacing).

Why say this, because in JS array storage

// The JSArray describes JavaScript Arrays
// Such an array can be in one of two modes:
// - fast, backing storage is a FixedArray and length <= elements.length();
// The storage structure is FixedArray, and the array length <= elements.length(). Push or POP may be accompanied by dynamic expansion or reduction

// Please note: push and pop can be used to grow and shrink the array.
// - slow, backing storage is a HashTable with numbers as keys
// The storage structure is HashTable, and the array subscript is used as key
class JSArray: public JSObject {
 public:
  // [length]: The length property.
  DECL_ACCESSORS(length, Object)
    
  // ...
   
  // Number of element slots to pre-allocate for an empty array.
  static const int kPreallocatedArrayElements = 4;
};
Copy the code

That is, you can see that JSArray inherits from JSObject, so in JavaScript, an array can be a special object that stores data internally as key-value, so arrays in JavaScript can hold different types of values

Advantages of arrays

  • Random access: Data can be randomly accessed at any location in an array by subscript

The time complexity of random access by subscript is O(1)

An array of features

  • Array inserts

We already know that an array is a contiguous chunk of memory, but what if we want to insert a new element into k? In this case, you need to move all elements after k one bit back and insert new elements in the position of k index.

  • delete

In fact, delete operation is very similar to insert. Similarly, if I want to delete the element in the index position of K in the array, we need to remove it, in order to maintain the continuity of memory, we need to move all the elements after K forward one bit. In this case, the time complexity is also O(n).

  • To find the

For example, if we want to find if there is an element of 2 in an array, what does the computer have to do?

If it’s a human, with a small amount of data, we can see at a glance if there’s a 2 element, but a computer doesn’t. The computer needs to match from index 0 down until it matches a 2 element

  • read

We have emphasized that arrays have the same data type and a contiguous piece of linear memory. Therefore, based on the above characteristics, arrays have excellent read performance and time complexity of O(1). Compared with linked lists, binary trees and other data structures, it has obvious advantages.

So how can arrays achieve such low time complexity?

Given that our array memory address is start, the element type is size, and the array index is I, we can easily obtain the address formula for the array memory address:

arr[i]_address = start + size * i
Copy the code

For example, if we want to read the value of ARr [3], we only need to substitute 3 into the addressing formula, and the computer can query the corresponding element in one step. Therefore, the time complexity of array reading is only O(1).

conclusion

In JavaScript, JSArray inherits from JSObject, or it’s a special object that stores data internally as key-value, so arrays in JavaScript can hold different types of values. It has two storage methods, fast array and slow array. When initializing an empty array, use fast array, fast array uses continuous memory space, when the array length reaches the maximum, JSArray will dynamically expand to store more elements, compared to slow array, performance is much better. When there are too many holes in an array, it is converted to a slow array, which stores data in the form of a hash table (key-value) to save memory space.


let res = new Array(100000).fill(10)
console.log(res)
var arr=new Array(100000).fill(100);
console.time('timer')
arr[0];
console.timeEnd('timer')

console.time('timer')
arr[100000-1];
console.timeEnd('timer')
Copy the code

reference

The performance test

jsperf.com/

07 –a.b.c.da['b']['c']['d']Which has higher performance?

  • For common compiled languages (such as Java), the compilation steps are: lexical analysis -> parsing -> semantic checking -> code optimization and bytecode generation.

  • For interpreted languages (such as JavaScript), parsing -> parsing -> syntax tree is the place to start explaining execution.

    • Lexical analysis is converting a char stream into a token stream
    • Syntax analysis into AST (Abstract Syntax Tree)
    • Precompile, when the JavaScript engine parses the script, it processes all declared variables and functions at precompile time! And is pre-declared variables, and then pre-defined functions!
    • Explain execution. During execution, the JavaScript engine is strictly scoped, and the scope of JavaScript variables and functions is determined at definition time, not at execution time. In JavaScript, variable scope works in the function body, without block scope.

Refer to the reading

  • JavaScript interpreter
  • Zhihu column on the performance of the two simple comparison

08- Performance optimization

[TOC]

The introduction

What happens when you open a browser and type a url into the address bar, and then enter?

1. The keywords

  • The DNS
  • 304 the cache
  • TCP three-way handshake four-way handshake
  • The HTTP message
  • Redraw, reflux
  • Synchronous programming
  • event loop
  • Macro task, micro task
  • Process, thread
  • Stack memory
  • Heap memory
  • Lazy loading of images
  • The compression
  • Performance optimization
  • Browser storage
  • Caching mechanisms

Processes and threads

Process of 1.

An execution of a program that occupies a unique piece of memory. Is the basic unit of operating system execution.

  • A process has at least one running thread: the main thread, which is created automatically after the process starts
  • It is also possible to run multiple threads in a process at the same time, and we would say that a program is multithreaded
  • Data within a process can be directly shared by multiple threads, but data between multiple processes cannot be directly shared

(1). Browser process

  • Browser process: the main process of the Browser, responsible for the display of the Browser interface, and the management of each page, the ancestor of all other types of processes in the Browser, responsible for the creation and destruction of other processes it has only one!!!!!
  • Renderer: a web page rendering process that is responsible for rendering a page. You can have multiple renderers. Of course, the number of renderers is not necessarily equal to the number of pages you open
  • Various plug-in processes
  • Browsers on mobile devices may be different: Android does not support plug-ins, so there is no plug-in process. The GPU evolved into a thread of the Browser process, and the Renderer evolved into a service process of the operating system, which remains independent

Thread 2.

An independent execution unit within a process and the smallest unit of CPU scheduling. The basic unit of program running thread pool (Thread pool): store multiple thread objects container, realize the reuse of thread objects

Since jS is single threaded, it involves event loops, event polling, and event loops.

The HTTP request

1. The DNS

2.TCP three-way handshake four-way wave

3. HTTPS and HTTP

The HTTP response

How browsers render

1. Browser function

  • network

    • Browsers use web modules to download various resources, such as HTML text; Javascript code. The style sheet; Image; Audio and video files, etc.
    • The network part is important by nature because it takes a long time and requires secure access to resources on the Internet.
  • Resource management

    • Resources downloaded from the Internet or obtained locally need an efficient mechanism to manage them.
    • For example, how to avoid repeated downloads, how to cache resources and so on
  • Browse the web

    • Resource visualization
  • And so on…

2. Browser kernel

Refer to Baidu Encyclopedia

The most important and core part of the browser is the Rendering Engine, which is generally referred to as the “browser core”.

Different browser kernels interpret the syntax of the web page differently, so the same page may render differently in different browsers with different kernels, which is why web writers need to test the page display in different browsers.

The kernel classification Browsers that use the kernel
Trident (IE) Internet Explorer, Superior game, Windows of the World Browser, Avant, Tencent TT, Sleipnir, GOSURF, GreenBrowser and KKman, etc.
Gecko(firefox) [Mozilla Firefox](Baike.baidu.com/item/Mozill…Firefox), Mozilla SeaMonkey, Waterfox (64-bit open source version of Firefox), Iceweasel, Epiphany (earlier version), Flock (earlier version), K-Meleon.
Its (Google) Google Chrome,360 ultra speed browserAs well asSogou high-speed browserHigh-speed mode also uses Webkit as the kernel
Blink
Presto

3. Browser rendering mechanism

  • Browsers use a streaming layout model (Flow Based Layout)
  • The browser will putHTMLParsed intoDOM,CSSParsed intoCSSOM.DOMandCSSOMThe merge results in a render tree (Render Tree).
  • There are theRenderTree, we know the style of all the nodes, calculate their size and position on the page, and finally draw the nodes on the page.
  • Since browsers use streaming layouts, yesRender TreeIs usually done only once,buttableWith the exception of their internal elements, they may require multiple computations, usually taking three times as long as their equivalent elements. Why avoid themtableOne of the reasons for layout

4. Browser rendering engine

(1). Main modules

  • HTML parser

    • A parser that interprets HTML documents
    • Function: Interprets HTML text into a DOM tree
  • CSS parser

    • It is used to calculate style information for individual element objects in the DOM
    • Provide infrastructure for the layout
  • JavaScript engine

    • Using Javascript code, you can modify the content of a web page, as well as the CSS information
    • The javascript engine is able to interpret javascript code and modify the web content and style information through DOM interfaces and CSS tree interfaces to change the rendered results
  • Layout reflux

    • After the DOM is created, Webkit needs to combine its element objects with style information
    • Calculate their size, location and other layout information
    • Form an internal representation model that expresses all this information
  • Drawing module

    • Use graphics library to draw the nodes of each web page into image results after layout calculation

(2). Rendering process

Rendering tree construction, layout, and rendering Chinese

  1. When you encounter HTML tokens, call the HTML parser to parse them into tokens (a token is a serialization of tag text) and build a DOM tree (a memory that holds tokens and establishes relationships between them)
  2. Encountering a style/link tag calls the parser to process the CSS tag and build a CSS style tree, known as CSSOM
  3. When script tags are encountered, javascript parsers are called to handle script tags, bind events, modify DOM /CSS trees, etc
  4. Merge the DOM and CSS trees into a render tree
  5. Render from the render tree to calculate geometric information for each node (this process depends on the graphics library)
  6. Draw the individual nodes to the screen.

5. Browser rendering is blocked

(1).css style rendering blocks

Only external CSS introduced by link can cause blocking

(2). JS blocked

Performance optimization

1. Reduce HTTP requests

2. Reduce DOM redrawing and backflow

(1). Redrawn

Redraw a node whose geometry or style changes without affecting the layout, such as outline, visibility, color, background-color, etc. Redraw is expensive because the browser must verify the visibility of other node elements in the DOM tree.

(2). Return

Backflow is when layout or geometry properties need to be changed. Backflow is a key factor affecting browser performance because it involves updating the layout of part of the page (or the entire page). The backflow of an element can result in subsequent backflow of all its child elements, as well as subsequent nodes in the DOM and ancestor node elements. Some bosses are also used to calling it a rearrangement

When does a browser backflow occur
  • Add or remove visible DOM elements
  • The position of the element changes
  • The size of the element changes (including margins, inner borders, border size, height, width, etc.)
  • Content changes, such as text changes or an image being replaced by another image of a different size.
  • When the page is first rendered (which is inevitable)
  • Browser window size changes (because backflow calculates element position and size based on viewport size)

(3). Browser optimization

Most modern browsers are batch update layout through the queue mechanism, the browser will put the modification operations in the queue, at least one browser refresh (16.6 ms) will empty the queue, but when you get the layout information, the queue may affect the properties or methods return value of the operation, if not, the browser will be forced to empty the queue, Trigger backflow and redraw to ensure the correct value is returned.

These include the following attributes or methods:

  • offsetTop,offsetLeft,offsetWidth,offsetHeight
  • scrollTop,scrollLeft,scrollWidth,scrollHeight
  • clientTop,clientLeft,clientWidth,clientHeight
  • width,height
  • getComputedStyle()
  • getBoundingClientRect()

(4). Summary

Redraw does occur, redraw does not necessarily cause redraw how to minimize redraw rearrangement?

  1. CSS
    • usetransformalternativetop

    • Use visibility instead of display: None, because the former will only cause redraw and the latter will cause backflow (changing the layout)

    • Avoid using a table layout because a small change can cause the entire table to be rearranged.

    • If possible, change the class at the very end of the DOM tree. Backflow is inevitable, but its impact can be reduced. Changing the class as far down the DOM tree as possible limits the scope of backflow, affecting as few nodes as possible.

    • Avoid multiple inline styles and CSS selectors match from right to left to avoid too many nodes.

      <div>
        <a> <span></span> </a>
      </div>
      <style>
        span {
          color: red;
        }
        div > a > span {
          color: red;
        }
      </style>
      Copy the code

      For the first style, the browser just needs to find all the SPAN tags on the page and set the color, but for the second style, the browser needs to find all the SPAN tags, then find the A tag on the SPAN tag, and finally find the div tag. Then color span tags that match this condition, and the recursive process becomes complicated. So we should avoid writing too specific CSS selectors as much as possible, and add as few meaningless tags to THE HTML as possible to keep the hierarchy flat.

    • Apply the animation effect to elements with position set to Absolute or fixed to avoid affecting the layout of other elements. This is just a redraw, not a backflow. Also, control the animation speed by using requestAnimationFrame. See requestAnimationFrame for details.

    • Avoid using CSS expressions, which may cause backflow.

    • If a node that is frequently redrawn or reflow is set as a layer, the layer can prevent the rendering behavior of this node from affecting other nodes, such as will-change, video, iframe, etc., and the browser will automatically turn this node into a layer.

    • CSS3 hardware acceleration (GPU acceleration) : CSS3 hardware acceleration enables transform, opacity, and filters to be redrawn without causing backflow. Other properties of animations, such as background-color, will still cause backflow redraw, but it can still improve the performance of those animations.

  2. JavaScript
    • Avoid frequent manipulation of styles, it is better to rewrite it oncestyleProperty, or define the style list asclassAnd change it onceclassProperties.
    • Avoid frequent operationsDOM, create adocumentFragmentApply all of them to itDOM manipulation, and finally add it to the document.
    • Avoid frequently reading properties that cause backflow/redraw, and if you do need to use them more than once, cache them in a variable.
    • Use absolute positioning on elements with complex animations to keep them out of the document stream, which would otherwise cause frequent backflow of parent elements and subsequent elements.

Refer to the reading

  • Do you really understand reflux and redraw
  • Performance optimization related references

09 -props

Understand the Prop

Basic usage

<! -- kebab-case in HTML -->
<blog-post post-title="hello!"></blog-post>
Copy the code
Vue.component('blog-post', {
  // In JavaScript it is camelCase
  props: ['postTitle'].template: '<h3>{{ postTitle }}</h3>'
})
Copy the code

Common type

An array of strings

props: ['title'.'likes'.'isPublished'.'commentIds'.'author']
Copy the code

Form of object

props: {
  title: String.likes: Number.isPublished: Boolean.commentIds: Array.author: Object.callback: Function.contactsPromise: Promise // or any other constructor
}
Copy the code

summary

In general, it can be divided into passing static values and passing dynamic values through V-bind

  • Passing a number
  • Pass a Boolean value
  • Passing in an array
  • Passing in an object
  • Pass in all attributes of an object

post: {
  id: 1.title: 'My Journey with Vue'
}
Copy the code

The following two approaches are equivalent

<blog-post v-bind="post"></blog-post>
Copy the code
<blog-post
  v-bind:id="post.id"
  v-bind:title="post.title"
></blog-post>
Copy the code

In Vue, why can’t a child component modify a Prop passed by its parent?

What happens when you try to modify it

Start by creating a file to demonstrate props passing values (parent component passing data to child components)

<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
    <title>Vue-prop</title>
  </head>
  <body>
    <div id="app">
      {{ message }}

      <hr />
      <ol>
        <! Create a todo-item component instance -->
        <todo-item todo="Learning"></todo-item>
      </ol>
    </div>

    <script src="./vue.js"></script>
    <script>
      // A component is essentially a Vue instance with predefined options
      // Register a TODO component
      Vue.component("todo-item", {
        template: '
       
  • {{todo}}
  • < button@click = "changeProps"> Try to change prop
    ' from the parent component
    .props: ["todo"].methods: { changeProps() { console.log('button trigger for child component'); this.todo = "Play"; }}});var vm = new Vue({ el: "#app".data() { return { message: "hello"}; }});
    </script> </body> </html> Copy the code

    What is the result? The data can also be modified successfully, but the console will send a warning

    vue.js:634 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "todo"
    Copy the code

    Unidirectional data flow

    All prop forms a one-way downlink binding between their parent prop: updates to the parent prop flow down to the child, but not the other way around. This prevents accidental changes in the state of the parent component from the child, which can make the data flow of your application difficult to understand.

    Additionally, every time the parent component is updated, all prop in the child component will be refreshed to the latest value. This means that you should not change a prop inside a child component. If you do, Vue will issue a warning in the browser console.

    To put it simply, vUE processes the data from the parent component in this way to facilitate the monitoring of the flow of data. Once an error occurs, it can locate the error position more quickly.

    Under what circumstances do we change this prop

    props: ['initialCounter'].data: function () {
      return {
        counter: this.initialCounter
      }
    }
    Copy the code
    • Case one: This prop is used to pass an initial value; This child component next wants to use it as a local prop data. In this case, it is best to define a local data property and use the prop as its initial value.With the help of the data
    props: ['size'].computed: {
      normalizedSize: function () {
        return this.size.trim().toLowerCase()
      }
    }
    Copy the code
    • The second caseThis prop is passed in as a raw value and needs to be converted. In this case, it is best to use the value of the prop to define a calculated propertyBy calculating properties

    If so, how does Vue monitor and warn about property changes

    Here we can go to the source code to find the answer, after all, the real warning hints are given by vue

    SRC >core>instance>state.jsCopy the code
    
    function initProps (vm: Component, propsOptions: Object) {
      const propsData = vm.$options.propsData || {}
      const props = vm._props = {}
      // cache prop keys so that future props updates can iterate using Array
      // instead of dynamic object key enumeration.
      // Cache prop keys for future updates to props can iterate with arrays instead of dynamic object enumerations
      const keys = vm.$options._propKeys = []
      constisRoot = ! vm.$parent// root instance props should be converted
      // Not root component
      if(! isRoot) { toggleObserving(false)}for (const key in propsOptions) {
        keys.push(key)
        const value = validateProp(key, propsOptions, propsData, vm)
        /* istanbul ignore else */
        // Check whether it is in a development environment
        if(process.env.NODE_ENV ! = ='production') {
          const hyphenatedKey = hyphenate(key)
          if (isReservedAttribute(hyphenatedKey) ||
              config.isReservedAttr(hyphenatedKey)) {
            warn(
              `"${hyphenatedKey}" is a reserved attribute and cannot be used as component prop.`,
              vm
            )
          }
          // If not, the change is from a child component, triggering a warning
          /** * the fourth function passed in is a custom set function, which triggers the fourth function */ when props is modified
          defineReactive(props, key, value, () = > {
            if(! isRoot && ! isUpdatingChildComponent) { warn(`Avoid mutating a prop directly since the value will be ` +
                `overwritten whenever the parent component re-renders. ` +
                `Instead, use a data or computed property based on the prop's ` +
                `value. Prop being mutated: "${key}"`,
                vm
              )
            }
          })
        } else {
          // In a development environment, Set is triggered to determine whether the key is being modified in updatingChildren
          defineReactive(props, key, value)
        }
        // static props are already proxied on the component's prototype
        // during Vue.extend(). We only need to proxy props defined at
        // instantiation here.
        if(! (keyin vm)) {
          proxy(vm, `_props`, key)
        }
      }
      toggleObserving(true)}Copy the code
    src>core>observer>index.js
    Copy the code
    /** * Define a reactive property on an Object. */
    export function defineReactive (
      obj: Object,
      key: string,
      val: any,
      customSetter?: ?Function, shallow? : boolean) {
      const dep = new Dep()
    
      const property = Object.getOwnPropertyDescriptor(obj, key)
      if (property && property.configurable === false) {
        return
      }
    
      // cater for pre-defined getter/setters
      const getter = property && property.get
      const setter = property && property.set
      if((! getter || setter) &&arguments.length === 2) {
        val = obj[key]
      }
    
      letchildOb = ! shallow && observe(val)Object.defineProperty(obj, key, {
        enumerable: true.configurable: true.get: function reactiveGetter () {
          const value = getter ? getter.call(obj) : val
          if (Dep.target) {
            dep.depend()
            if (childOb) {
              childOb.dep.depend()
              if (Array.isArray(value)) {
                dependArray(value)
              }
            }
          }
          return value
        },
        set: function reactiveSetter (newVal) {
          const value = getter ? getter.call(obj) : val
          /* eslint-disable no-self-compare */
          if(newVal === value || (newVal ! == newVal && value ! == value)) {return
          }
          /* eslint-enable no-self-compare */
          if(process.env.NODE_ENV ! = ='production' && customSetter) {
            customSetter()
          }
          // #7981: for accessor properties without setter
          if(getter && ! setter)return
          if (setter) {
            setter.call(obj, newVal)
          } else{ val = newVal } childOb = ! shallow && observe(newVal) dep.notify() } }) }Copy the code

    thinking

    Does the console warn if it is passed a referenced data type?

     <todo-item todo="Learning" :todolist="todolist"></todo-item>
    Copy the code
    Var vm = new Vue({el: "#app", data() {return {message: "hello", todolist: [{id: "1", todo: "dinner"}]}; }});Copy the code

    Recommended reading

    • Vue official website props section