Summary of the latest front-end interview knowledge points-2023 (3w+ words, long length)

2023- Summary of front-end interview knowledge points

Written at the top, the coordinates are in Chengdu. On March 16, the previous company resigned and has now joined the new company. Generally speaking, the recruitment of front-end positions at this stage is not as active as in the past for gold, silver, and silver. The fragmented interview opportunities, coupled with the introversion of insiders, I hate.
But in the process of actively interviewing and preparing for the interview, you can pick up or deepen your impression of the forgotten front-end foundation in previous job development. The following are some of the front-end knowledge points that I have been asked during the personal interview process, record and share, I wish you an early entry!
Basically, it is the text content typed out by my own keyboard. There may be typos. Welcome to point out the wrong knowledge points.

Overview of interview questions

vue2与vue3的区别
重绘重排(回流)
防抖节流
双向绑定原理
react样式实现作用域
组件传参方式
websocket三次握手
http三次握手、浏览器输入一个url到页面显示的过程描述
webpack loader作用
webpack深入(优化、使用)
new 一个对象的过程
js的优化、css的优化、项目界面优化
前端单元模块测试经历
es6与es7 es8
es6的新增特性
this指向分类深入了解
vue2与vue3的响应式原理(es5的defineProperty与es6的proxy的区别对比)
vuex实现数据持久的方法
文件上传组件请求头判断文件类型
垃圾回收机制

async 中使用awiat 与.then的区别-- 阻塞
css 动画样式实现平移 旋转 缩放等
css 阴影 参数讲解
webpack loader使用 基本配置 
vite与webpack
vue2 vue3的区别
typescript 类型(对象key字符串,值number的表示方式)
interface type的区别
typescript 类型有哪些、泛型
map数据格式
函数闭包、内存溢出原因
垃圾回收机制
var let const 区别与实际应用
js作用域
promise
vue组件父子传参
vite冷启动
commonjs 与 esmodule

浏览器http1.0 的缓存
promise原理
执行上下文
link与@import css的区别
js浮点数丢失精度原因与解决方案


flex布局属性
css实现三角形,扇形
线程与进程
http缓存
自适应布局
cdn cdn解决更新缓存问题
递归函数的作用域是否一样? 不一样 因为局部执行上下文是在执行function时才会被创建,每次执行方法时都会创建一个局部执行上下文(执行fun时有一个入栈操作,执行完成后有一个出栈操作,在栈底部时全局执行上下文,这也是为什么基础数据存在栈上,因为栈需要维护js运行时的执行上下文切换)
递归栈溢出解决方案---尾递归
尾调用优化原理
微任务是哪些宏任务是哪些 事件队列
设计模式(观察者模式、发布订阅模式)
target currenttarget区别
点击事件发生的事件过程(捕获,冒泡)
链表
vue的源码(响应式、模板渲染)
js是单线程,怎么执行异步任务的
vue组件中定义一个变量a = 1在页面显示,使用for循环去改变100次变量的值,页面会渲染多少次
执行js同步代码时遇到一个dom的样式修改,浏览器会怎么操作,直接渲染界面还是
vue定义全局组件的方法

javascript-related

1. Common optimization methods for js code

1. Use event delegation (event proxy): reduce the number of event registrations and memory usage, and improve performance.
2. Avoid using global variables: In JavaScript, accessing global variables will be very slow, because if the variable is not found in one scope, it will go all the way up to the global scope.
3. Reduce DOM operations: DOM operations consume a lot of CPU and memory, so it is best to only operate DOM when necessary.
4. Object cache: If you need to create the same object repeatedly, it is best to cache it to avoid the performance loss caused by frequent creation and destruction of objects.
5. Use throttling and anti-shake technology: throttling and anti-shake can effectively reduce the frequency of function execution.
6. Reduce the length of the scope chain: the longer the scope chain, the longer the variable lookup and access time.
7. Avoid repeated calculations: For example, some constants and calculation results should be cached to avoid repeated calculations.
8. Function tail call optimization (such as tail recursion)
Regarding tail recursion:
1. Only when the internal variables of the outer function are no longer used (no closure is formed), the call frame of the inner function will replace the call frame of the outer function
2. Inside the function, the tail call is the last statement.
3. The result of the tail call is returned as a function value
. If the above three requirements are met, it will be automatically optimized by the js engine, otherwise the tail call optimization cannot be recognized.

Tail calls have always existed. Tail call optimization is added in js engines (such as v8) that support es6. Tail recursive optimization only takes effect in strict mode. It can also be used in es6 module, because es6 module follows strict mode by default

Tail recursion optimization - solve the stack overflow problem:

// 非尾调用 (计算n的阶乘,最多需要保存n个调用记录,复杂度O(n))
function factorial(n) {
    
    
  if (n === 1) return 1;
  return n * factorial(n - 1);
}
// 尾调用 (只保留一个调用记录,复杂度O(1))
function factorial(n, total) {
    
    
  if (n === 1) return total;
  return factorial(n - 1, n * total);
}

Two, es5 constructor and inheritance

// 构造函数继承
// 1.能给父类传参 2.每个新实例引入的构造函数属性是私有的 3.不能继承父类原型上的东西,即不能共用一些公共方法和属性
function A(name) {
    
    
  this.name = name;
  this.age = 1;
  this.say = function () {
    
    
    console.log(this.name, this.age);
  };
}
A.prototype.sayOk = function () {
    
    
  console.log(this.name, "ok");
};
function B(name) {
    
    
  A.call(this, name); // *****
  this.age = 2;
  // this.say = function () {
    
    
  //     console.log(this.name, this.age)
  // }
}

const b = new B("nb");
console.log(b.say());
console.log(b.sayOk()); // 不能继承原型上的属性方法

// 原型继承
// 1.能够继承父类原型上的方法和属性 2.父类不能入参 3.所有子类实例会共享父类的引用类属性
function AA(name) {
    
    
  this.name = name || "AA";
  this.age = 1;
  this.say = function () {
    
    
    console.log(this.name, this.age);
  };
}
AA.prototype.sayOk = function () {
    
    
  console.log(this.name, "ok");
};

function BB() {
    
    
  this.age = 2;
}
BB.prototype = new AA(); //**** child的原型指向parent的实例
BB.prototype.constructor = BB; // 纠正child原型上的构造函数
const bb = new BB("nbb");
bb.say();

// 组合继承(原型加借用构造函数)
// 1.能继承父类的实例属性与方法以及父类原型上的属性与方法 2.父类能入参 3.子类实例引入的构造函数属性是私有的 4.调用两次父类构造函数()
function Parent(name) {
    
    
  this.name = name;
  this.arr = [1];
  this.age = 1;
  this.getAge = function () {
    
    
    console.log(this.age);
  };
}
Parent.prototype.sayOk = function () {
    
    
  console.log(this.name, "say ok");
};

function Child(name) {
    
    
  Parent.call(this, name);
  this.age = 2;
}

Child.prototype = new Parent();
Child.prototype.constructor = Child;

Child.prototype.sayWhy = function () {
    
    
  console.log(this.name + " say why");
};

let c1 = new Child("c1");
console.log(c1.__proto__.constructor === Child);

// 原型式继承
// 在已有一个对象的基础上,再创建一个新对象
let obj = {
    
    
  name: "已存在的对象",
  age: "100岁",
  friend: [1, 2, 3],
};
// 本质是一次浅拷贝
//
function object(o) {
    
    
  // 创建一个临时的构造函数
  function F() {
    
    }
  F.prototype = o;
  return new F();
}
// 与原型继承相似 子类实力会共享父类的引用类属性 ;不需要单独创建构造函数
const o1 = object(obj);
o1.friend.push(6);
o1.getNum = function () {
    
    
  console.log(this.friend);
};
const o2 = object(obj);
o2.getNum = function () {
    
    
  console.log(this.friend);
};
o1.getNum();
o2.getNum();

// 寄生式继承
// 在原型式的继承上加一个function包裹,扩展新对象的效果和方法
// 不需要单独创建函数 ;通过该方式给对象扩展 难以复用。
function createAnother(o) {
    
    
  const _o = object(o);
  _o.vue = "ok";
  _o.useVue = function () {
    
    
    console.log("vue is " + this.vue);
  };
  return _o;
}

const o3 = createAnother(obj);
o3.useVue();

// 寄生组合式继承
// 借用父类构造函数、把子类的原型指向通过寄生式继承父类原型的对象
function object(o) {
    
    
  // 创建一个临时的构造函数
  function F() {
    
    }
  F.prototype = o;
  return new F();
}
function createAnother(o) {
    
    
  const _o = object(o);
  return _o;
}
function People(name) {
    
    
  this.name = name;
  this.age = 100;
  this.eat = function () {
    
    
    console.log(this.name + "eat....");
  };
}
People.prototype.bloodColoe = "red";
People.prototype.speek = function (s) {
    
    
  console.log(this.name + "说:" + s);
};

function Man(name) {
    
    
  People.call(this, name);
  this.sex = "男";
}

Man.prototype = createAnother(People.prototype);
// Man.prototype = Object.create(People.prototype)
Man.prototype.constructor = Man;

// new 的过程

//  1.创建一个空对象  2.将空对象的__proto__属性指向构造函数的原型对象 3.将构造函数中的this指向创建的空对象(call apply)并执行构造函数 4.如果构造函数没有返回对象(不包括null)则返回obj(this)
function T() {
    
    
  this.a = 1;
  this.b = 2;
  return {
    
    };
}
const t = new T();
console.log(t);

3. The process of new an object

1.
1. Create an empty simple JavaScript object (ie {}); 2. Add the property proto
to the object newly created in step 1, and link this property to the prototype object of the constructor; 3. Add the object newly created in step 1 As the context of this; 4. If the function does not return an object, return this. 2. Set the type of the target object (Target) to a function (constructor) to create a new empty object and bind it to Target.prototype. Executes the Target function and sets this to the newly created object. That is, the function can use this to refer to the new object during the call. If the return value is non-null, use that value as the result of the constructor. Otherwise, return the newly created object






4. Anti-shake and throttling

Debounce and throttling are two ways to handle frequently fired functions in JavaScript to optimize page performance.

Anti-shake (debounce):
When an event is triggered frequently, the event will not be actually executed until the event is not triggered again within a certain time interval. Implementation
principle:
use timers and closures to implement. Every time an event is triggered, the timer will be cleared first, and the callback function in the timer will be executed only when the event stops triggering

function debounce(fn, delay) {
    
    
  let timer = null;
  return function () {
    
    
    if (timer) clearTimeout(timer);
    const self = this;
    const args = arguments;
    timer = setTimeout(function () {
    
    
      fn.apply(self, args);
    }, delay);
  };
}

Throttle:
The function will only be executed once within a certain time interval, which is equivalent to setting the minimum time interval for execution.
Implementation principle:
record the timestamp lastTime of the last execution, and within the next timestamps, if the client triggers the event repeatedly, it will only return the result of the last call; only when the time is greater than timestamps, it will recalculate and return new value.

// 1
function throttle(fn, delay) {
    
    
  let lastTime = 0;
  return function () {
    
    
    const currentTime = +new Date();
    const self = this;
    const args = arguments;
    if (currentTime - lastTime > delay) {
    
    
      fn.apply(self, args);
      lastTime = currentTime;
    }
  };
}

// 2
function throttle(fn, delay) {
    
    
  let timer = null;
  return function () {
    
    
    const self = this;
    const args = arguments;
    if (!timer) {
    
    
      timer = setTimeout(() => {
    
    
        fn.apply(self, args);
        clearTimeout(timer);
      }, delay);
    }
  };
}

5. Overview of promise/A+ specification

Promise has three states: pending, fulfilled, or rejected; "standard Promise/A+ 2.1"
new promise, you need to pass an executor() executor, and the executor will execute immediately; executor
accepts two parameters, namely resolve and reject;
promise The default state of the promise is pending;
promise has a value to store the value of the successful state, which can be undefined/thenable/promise; "standard Promise/A+ 1.3"
promise has a value of reason to save the failed state; "standard Promise/A+ 1.5"
promise only It can go from pending to rejected, or from pending to fulfilled. Once the state is confirmed, it will not change again;
promise must have a then method, and then receives two parameters, which are the callback onFulfilled when the promise succeeds, and the callback onRejected when the promise fails; "Specification Promise/A+ 2.2" If the promise is successful when then is called, onFulfilled is
executed, and the parameter is the value of the promise;
if the promise has failed when then is called, onRejected is executed, and the argument is the reason of the promise;
If an exception occurs, the exception will be passed as a parameter to the next then failed callback onRejected;
The parameters onFulfilled and onRejected of then can be defaulted. If onFulfilled or onRejected is not a function, ignore it, and the previously returned value can still be obtained in the following then; "Specification Promise/A+ 2.2.1, 2.2.1.1, 2.2 .1.2"
promise can be then multiple times, and each time the promise.then method is executed, it will return a "new promise"; "Specification Promise/A+ 2.2.7"
if the return value x of then is an ordinary value, then The result will be passed as a parameter to the successful callback of the next then;
if an exception is thrown in then, the exception will be passed as a parameter to the failed callback of the next then; "Specification Promise /A+ 2.2.7.2 "
If the return value x of then is a promise, then it will wait for the promise to be executed. If the promise succeeds, it will go to the success of the next then; if it fails, it will go to the failure of the next then; if it throws If there is an exception, go to the failure of the next then; "Specification Promise/A+ 2.2.7.3, 2.2.7.4"
If the return value x of then and promise are the same reference object, resulting in a circular reference, an exception is thrown and the exception is passed to In the failure callback of the next then; "Specification Promise/A+ 2.3.1"
If the return value x of then is a promise, and x calls the resolve function and the reject function at the same time, the first call takes precedence, and all other calls are ignored ; "Specification Promise/A+ 2.3.3.3.3"

If a non-promise value is returned in promise.then(), the value will be obtained in the next .then(); if a promise is returned, it will be judged according to the resolution value of the promise, and if it is resolve, it will be in the next Get the resolve value in .then(). If it is a reject, it will get the value in the next catch. If no operation is performed, the subsequent .then or .catch operation will not be triggered. promise.resolve() returns a promise object that resolves successfully, and promise.reject() returns a promise object that resolves incorrectly

6. Realize a Currie function encapsulation

Currying a function is actually saving the variables that have been called multiple times in the closure, and checking whether the number of variables is equal to the number of formal parameters of the original function for each call. If not equal, continue recursively. Process until equal

* The length attribute of function indicates the number of formal parameters of the method

function curry(fn) {
    
    
  return function curryFn() {
    
    
    // 1. 一次性将所有参数传完
    // arguments
    if (arguments.length < fn.length) {
    
    
      // 2. 没有一次性传完
      var _arg = Array.from(arguments);
      return function () {
    
    
        // 当这个匿名函数被调用时
        // 看这一传递进来的参数 + 上一次的参数 === fn.length
        return curryFn(...Array.from(arguments).concat(_arg));
      };
    }
    return fn(...arguments);
  };
}

// es6 rest参数 替代arguments(类数组)获取剩余参数,并且本身就是数组类型。箭头函数替代函数声明式或函数表达式、匿名函数等
const _curry = (fn) => {
    
    
    const myCurry = (...args) =>
        fn.length === args.length ?
            fn(...args) :
            (...arg) => myCurry(...args, ...arg)
    return myCurry
}
const _myCurry = _curry(add)

Seven, event queue

1. Execute the global Script synchronization code to form an execution stack;

2. When the above asynchronous task is encountered during code execution, the macro task callback will be added to the macro task queue as described above, and the micro task callback will be added to the micro task queue;

3. However, the callback function is not executed immediately after being placed in the task queue; it will wait until all the synchronization tasks in the execution stack are executed and the stack is cleared before the engine will go to the task queue to check whether there are tasks, and if there are, these tasks will be deleted Join the execution stack, and execute!

4. After the execution stack is emptied, it will first check whether there are tasks in the microtask queue, and add the tasks to the execution stack one by one for execution. After the tasks in the microtask queue are all cleared, and the execution stack is also cleared, check whether there are tasks in the macrotask queue, and the tasks that are fetched from the head of the queue are put into the execution stack for execution, and other tasks may generate microtasks. Task, when the task result in this execution stack is cleared, it will check the microtask queue again...

5. The engine will execute the above steps cyclically, which is Event Loop

8. What are the microtasks and what are the macrotasks?

Microtasks: postMessage, MutationObserve, promise.then, process.nextTick
Red tasks: setTimeout, setInterval, setImmediate, I/O

9. When executing js code, the execution order of synchronization tasks, micro tasks, macro tasks, and dom rendering

1. Synchronization task 2. Micro task 3. DOM rendering 4. Macro task

10. js is single-threaded, how to implement asynchronous tasks

Although javascript is single-threaded, the browser that runs js is multi-threaded. It provides timing trigger threads, event trigger threads, etc. to realize the asynchronous logic of js

11. Written test - event queue

// 题一
const p1 = new Promise((resolve, reject) => {
    
    
    console.log('p1')
    setTimeout(() => {
    
    
        resolve('success p1')
    }, 0)
})
const p2 = p1.then(() => {
    
    
    console.log('p1-p2')
    return 818
})
const p3 = p2.then(res => {
    
    
    console.log('p3', res)
    // return Promise.resolve('p3 Promise')
    return Promise.resolve(new Promise((resolve, reject) => {
    
    
        resolve('test')
    }))
})
const p4 = p3.then(res => {
    
    
    console.log('p4:', res)
})
setTimeout(() => {
    
    
    console.log('setTimeout 10')
}, 10)
setTimeout(() => {
    
    
    console.log('setTimeout 0')
}, 0)
console.log('just test')
/* 
p1
just test
p1-p2
p3 818
p4: p3 Promise
setTimeout 0
setTimeout 10


*/

// 题二
const myPromise = Promise.resolve('42');
myPromise.then(res => {
    
    
    console.log(res)
    // return Promise.resolve('12').then(res => {
    
    
    //     return Promise.resolve('what')
    // })
    // return new Promise((res, rej) => {})
    return Promise.reject('what')
}).then(res => {
    
    
    console.log(res)
}).then(res => {
    
    
    console.log('1')
}).then(res => {
    
    
    console.log('2')
}).then(res => {
    
    
    console.log('3')
}).then(res => {
    
    
    throw new Error('hhh')
    console.log('4')
}).then(res => {
    
    
    console.log('5')
}, err => {
    
    
    console.log('errr 5')
}).catch(err => {
    
    
    console.log('errrrr')
})

12. Written test - file upload judge file type by header file

Through the input tag, type=file, realize the function of uploading files and judge the file type

const allowedType = {
    
    
    'FFD8FFE0': 'jpg',
    '89504E47': 'png',
    '47494638': 'gif',
    "52494646": 'webp'
}
// 通过头文件 判断上传文件格式
function fileType(file) {
    
    
    const fileReader = new FileReader()
    fileReader.readAsArrayBuffer(file)
    return new Promise((resolve, reject) => {
    
    
        fileReader.onload = (e) => {
    
    
            try {
    
    
                let uint8Array = new Uint8Array(e.target.result).slice(0, 4)
                // let key = [...uint8Array].map(s => s.toString(16).toUpperCase().padStart(2, '0')).join('')
                let key = Array.prototype.map.call(uint8Array, s => s.toString(16).toUpperCase().padStart(2, '0')).join('')
                console.log(key, allowedType[key])
                resolve(typeof allowedType[key] === 'string')
            } catch (error) {
    
    
                reject(error)
            }
        }
    })
}

function clickBtn () {
    
    
    const fileInput = document.querySelector('#file')
    console.log(fileInput.files)
    fileType(fileInput.files[0]).then(res => {
    
    
        console.log(res)
    })
}

css-related

1. Common optimization methods of css

Avoid using @import:
Reason: @import referencing external css will increase the number of page requests and the number of css files, resulting in slower page loading.
Solution: Include CSS in <head> using <link> tag.
Compress CSS files:
Reason: Deleting unnecessary characters such as unnecessary codes, comments, spaces, etc. can reduce file size and improve file download speed.
Solution: Use a CSS compression tool (for example: UglifyCSS, CSSNano, etc.).
Reasons for reducing the use of Float
: Float elements are more likely to cause the height of the root element to collapse, which affects the layout of other content and directly affects page performance.
Solution: Use Flexbox or Grid Layout instead of Float layout.
Reasons to use CSS Sprites
: Reduce HTTP requests and make web pages load faster.
Solution: Combine several small images into one large image, and use the background-position property to display the desired image area

2. The difference between link and @import

<link> is an HTML tag, and @import is a method provided by CSS;
<link> is loaded at the same time when the page is loaded, and @import will not be loaded until the equivalent CSS file is completely downloaded;
<link> supports the use of JS Manipulate DOM to dynamically load and change styles, while @import does not support

3. Responsive page design

Native html elements are responsive when no css is written. Responsive is mainly adjusted for fixed width or elements that affect the layout

First, you need to enable the meta tag name="viewport" and set the content attribute value to width=device-width, initial-scale=1.0. Because the default on the mobile page is to zoom the page on the PC to display the content, the user experience is not friendly and you need to zoom in to view the content. After setting device-width, the visible area of ​​the web page will take the actual width of the mobile device screen. Set initial- After scale=1.0, the normal scaling will be used, that is, 1:1 will not scale

1. Responsive container width
1. Use percentage width to make it automatically adjust the width size according to the visible area of ​​the screen
2. If you must use a fixed width, you can combine @media media query to query the width of the visible area, and then according to different Width of the visible area sets the width of the container

2. Responsive (horizontal) layout
, for example, using flex layout,
you can use flex-wrap and flex attributes to keep flex child elements at a minimum width and automatically wrap

If you are using grid layout, there is no problem with the vertical arrangement by default, but if it is a multi-column layout, if you set grid-template-columns: 1fr 1fr 1fr
and each column has a floating width, it will also appear like a flex layout.
Solution 1:
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr))
When the final width of the container is not enough to accommodate the minimum width of the column, the line will be displayed.
Solution 2:
Use @media according to the visual The width manually controls the number of columns

3. Responsiveness of the picture
1. The percentage width setting is used on the PC side, but there will still be display problems on the mobile side.
Solution on the mobile side:
1. Combine the attributes srcset and sizes of the img element to achieve responsiveness. When sizes are used, query the width of the visible area through @media. When the conditions are met, specify the width of the image through the second value. srcset according to the first The width specified by the second parameter, to use the image specified by the first parameter. The browser will automatically load images according to the pixel density and screen width

<img src="xx.png" srcset="
    xxx.png 1240w,
    xxx1.png 600w,
    xxx3.png 300w
" sizes="(max-width: 400px) 300px, (max-width: 900px) 600px, 1240px" />

2. Use the picture element combined with the source element to specify the url and media query of the picture, load different pictures in different viewable widths, and use the img element to load the guaranteed default picture

<picture>
    <source media="(max-width: 400px)" srcset="xxxx.png" />
    <source media="(max-width: 900px)" srcset="xxxx1.png" />
    <source media="(max-width: 1240px)" srcset="xxxx2.png" />
    <img src="xxx.png" />
</picture>

4. Responsive fonts
1. Use @media
2. Use floating units (rem em vw), vw may have a screen width that is too small and the font will be too small to display, which can be combined with calc (2rem + 2vw) 3.
@ media combined with floating units

Fourth, css realizes triangle and sector

1. Use border to add content h and w to 0 to realize the triangle
2. Use pseudo-class elements to realize
3. Use clip or clip-path to realize the clipping attribute.
The specific code is as follows:

<div class="sector"></div>
<div class="fan"></div>

<div class="triangle-up"></div>
<!-- <div class="triangle-down"></div>

<div class="triangle-left"></div>

<div class="triangle-right"></div> -->
<div class="clip"></div>
.triangle-up {
    
    
    width: 0;
    height: 0;
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    border-bottom: 10px solid red;
    /* border-top: 10px solid transparent; */
}


.triangle-down {
    
    
    width: 0;
    height: 0;
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    border-top: 10px solid green;
}

.triangle-left {
    
    
    width: 0;
    height: 0;
    border-top: 10px solid transparent;
    border-right: 10px solid brown;
    border-bottom: 10px solid transparent;
}

.triangle-right {
    
    
    width: 0;
    height: 0;
    border-top: 10px solid transparent;
    border-left: 10px solid yellow;
    border-bottom: 10px solid transparent;
}

.sector {
    
    
    width: 100px;
    height: 100px;
    background-color: red;
    border-radius: 50%;
    clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}

.fan {
    
    
    width: 0;
    height: 0;
    border-radius: 100% 100% 0 0;
    border-style: solid;
    border-width: 100px 60px 0 60px;
    border-color: #555555 transparent transparent transparent;
    position: relative;
}

.fan::before {
    
    
    content: "";
    position: absolute;
    left: -20px;
    top: 50%;
    width: 20px;
    height: 20px;
    background-color: #555555;
    border-radius: 50%;
    transform: translate(-50%, -50%);
}

.fan::after {
    
    
    content: "";
    position: absolute;
    right: -20px;
    top: 50%;
    width: 20px;
    height: 20px;
    background-color: #555555;
    border-radius: 50%;
    transform: translate(50%, -50%);
}
.clip{
    
    
    width: 300px;
    height: 300px;
    background-color: red;
    position: absolute;
    clip: rect(0px, 120px, 160px, 20px);
    transform: rotate(45deg);
}

typescript-related

1. Typescript type (object key string, representation of value number)

interface {
    
    
    [key:string]: number
}

Two, the difference between interface and type

In TypeScript, both interface and type are used to describe object types or other types. The main difference between them is:
interface can be used for declaration merging, that is, two interfaces with the same name will be automatically merged into a type union
type can be used to declare joint types and type aliases
When you need to define a joint type, you should use type The statement adjusts the hierarchy. And for any type definition that needs to extend, merge, or implement some kind of class specification, you should use interface

three,&

In TypeScript, & represents Intersection Types, which can combine multiple types into one type.

For example, there are two interfaces: User and Account, which can be merged into a "new" interface using &:

interface User {
    
    
    name: string;
}

interface Account {
    
    
    id: number;
}

type UserInfo = User & Account;

const user: UserInfo = {
    
    
    name: "Tom",
    id: 123456,
}

4. What data types are there in ts

Any: Indicates any type, that is, it can be any type of value.
Number: Represents numeric types, including integers and floating point numbers (binary, octal, and hexadecimal literals are supported).
String: Indicates the string type, including single quotes and double quotes, and template strings (using backticks ``).
Boolean: Boolean type, only two values: true and false.
Array: Indicates the array type, and there are two ways to define it: number[] indicates an array that can only store numeric types, and Array<number> indicates that it can also store only numeric arrays.
Tuple: Represents the tuple type, representing the number of known elements and an array of each element type, for example [string, number] represents a sequence of elements consisting of strings and numbers.
Enum: Indicates an enumeration type, which is used to give a friendly name to a set of values. For example, in the example below, the variable name representing the day of the week is given the corresponding English name.
Void: A type that represents undefined or null. It is generally not recommended to use it directly with declared variables, but it is the return value type of some functions.
Null and Undefined: represent null and undefined values ​​respectively (these two types are subtypes of all types)
Object: represent non-primitive types, that is, one of the six types except number, string, boolean, symbol, null and undefined outside the type. Using object to define an instance object is equivalent to using class in other languages.
It is worth noting that in TypeScript, the type definition of a variable can start with a lowercase character or an uppercase character. Beginning with lowercase characters is usually called the Primitive Type, and starting with uppercase characters is usually called the Object Type.

The details are as follows:
Basic types: number, boolean, string, null, undefined, symbol, void
Object types: Object, Function, Array, Tuple, Enum, Class, Interface, Type Alias ​​The above
are the data types in TypeScript, and some types are found It is not in JavaScript, such as Tuple (tuple type), other basic types are similar, and there are some special types that need to be gradually mastered in the follow-up learning process.

5. The way to define the function type in ts

Function declaration: use the function keyword to declare a function

function add(x: number, y: number): number {
    
    
  return x + y;
}

Function expressions: Assigning functions to variables simplifies the definition of explicit argument types.

const addFunc = (x: number, y: number): number => {
    
    
  return x + y
}

Interface Definition Function Type: Define an interface to describe the signature of this function.

interface Add {
    
    
  (x: number, y: number): number
}
const add: Add = (x, y) => x + y

Type aliases define function types: use type aliases to name function types.

type Add = (x: number, y: number) => number
const add: Add = (x, y) => x + y

http-related

1. The basis of http (Hypertext Transfer Protocol)

http is an
extensible transport protocol,
application layer protocol, and
client-server protocol.
HTTP is essentially stateless, and cookies can be used to create stateful sessions.
Scalability is mainly reflected in the header header configuration proposed by http1.0, as long as the header semantics of the client and the server are consistent (such as cookies, caches, etc.)

Two, the difference between http1.0 and http1.1

1. The difference between tcp connections
http1.0 default short connection client will establish a tcp connection when it initiates a request, and close the tcp connection after the server responds to the request. Each request will establish a tcp connection;
1.0 can enable the function of keeping the tcp connection persistent by setting the header Connection:Keep-Alive, which can be used in conjunction with Keep-Alive:max=5,timeout=120, indicating that the connection is at most 5 requests remain persistent, or the persistent state remains for 2 minutes
http1.1 The default persistent connection 1.1 gradually stops supporting the keep-alive connection, and uses an improved version of the persistent connection to replace it. The client configures the header Connection:close To close the tcp connection, the server will maintain a persistent
connection only when the message is correct, otherwise the server will
actively
disconnect
. Add cache-control header file to set strong cache, max-age relative time

Three, websocket three-way handshake (tcp three-way handshake)

SYN+ACK message. Among them, the ACK message is used to reply, and the SYN message is used to synchronize. The
essence is to confirm whether the generation and reception capabilities of both the client and the server are ok.

The first handshake: the client sends a SYN packet, telling the server to request a connection.
The second handshake: After the server receives the client's SYN packet (the server confirms that the client's sending capability is ok), it sends back a SYN-ACK packet to convey the confirmation message (indicating that the client's request has been received and the connection is agreed to be established) .
The third handshake: After the client receives the SYN-ACK packet from the server (the client confirms that the sending and receiving capabilities of the server are ok), it sends an acknowledgment packet ACK to the server (indicating that the server has received its request and Agree to establish a connection, and the server confirms that the receiving capability of the client is ok), and the TCP connection is successfully established at this time.
After the three-way handshake is completed, the client and server can send data to each other. After the connection is established, if you need to terminate the connection, you need to wave four times.

Four, tcp waved four times

Brief description: 1. The client initiates a request to close the connection. 2. The server receives the close request and returns to the client. The server has received the request to close the connection. 3. However, the server may still have unfinished message transmission at this time. , so it will send a FIN message to the client after the server finishes processing. 4. After receiving the FIN message from the server, the client generates an ACK response to the server

5. Browser cache (http cache) -- mainly caches static resources

Advantages of browser caching: reduce server burden, improve website performance, speed up the loading speed of client web pages, reduce redundant network data transmission, and improve server concurrent performance.

1. When an http request is made, the browser obtains the cached data or re-requests the background process
1. When the resource is loaded for the first time, the server returns 200, the browser downloads the resource file from the server, and caches the resource file and the response header. It is used to judge the timeliness of the cache when requesting data next time

2. When loading resources next time, due to the higher priority of the strong cache (the inspection time expires to judge the availability of the cache), first compare the time difference between this request and the last time the server returned 200 requests, if it does not exceed the cache- in the header The max-age (relative time) set by control—supported by http1.1 version, there is no expiration (hit), and you can use strong cache to directly obtain resources from the local. If the browser does not support http1.1, use the expires (absolute time) in the header to determine whether it is expired

3. If the cache resource has expired, it means that the strong cache is not hit, and the negotiation cache is started, and the If-None-Match is sent to the server (the server does not have a resource matching the Etag to obtain the data and return 200) and If- Modified-Since (the resource has been modified after Last-Modified (the last modification time stored in the response header), the data will be obtained and 200 will be returned, otherwise 304 will be returned, and the client will obtain the local cache) request

4. After the server receives the request, it first judges whether the requested resource has been modified according to the value of Etag. Combined with the conditional request header If-None-Match, if there is a resource with the same Etag value (hit), it means that it has not been modified and returns 304, the client uses a local cache; if there is no consistent Etag indicating that the resource has been modified, a new resource will be returned with the new Etag in the response header, and a status of 200 will be returned

5. If there is no Etag value in the request header, use the conditional request header If-Modified-Since to carry the Last-Modified of the last request for comparison. After the Last-Modified, whether the resource has been modified or not (hitting the negotiation cache) If it returns 304, the client uses local cache; if it is modified, it will return a new resource and carry a new Last-Modified value in the response header, and return 200

The version number is added to the resources of many websites. The purpose of this is: every time the JS or CSS file is upgraded, in order to prevent the browser from caching and force the version number to be changed, the client browser will re-download the new JS or CSS files to ensure that users can get the latest updates of the website in a timely manner. Import data such as cdn

2. Location of browser resource cache
1. service worker
2. memory (high reading efficiency, short persistence)
3. hard disk (large capacity, long persistence, slow reading)

6. Browser local storage

Describe Cookie, LocalStorage, SessionStorage

vue-related

1. How to deploy the vue project, and whether you have encountered the problem of refreshing 404

  1. Vue project deployment
    Just put the vue package file in the static folder specified by the server, and then make the web container run to access the project.
    Generally, nginx is used to realize it, and nginx can be started after configuration
  2. Refresh 404 problem
    In the case of history routing mode, 404 will appear after the deployed package is accessed, because when the history route is accessed by the browser, the path will be included in the HTTP request, and the server will reload the page according to the path.
    Vue is a single-page spa application. It can be seen from the package file that there is only one entry page index.html. It can be seen from the nginx configuration that when the browser opens the server address, it will be directed to index.html by default. However, other paths such as
    xx When .xx.com/login, the browser will refresh and direct to the corresponding interface of /login, but because the location of nignx has no relevant path configuration, and the server cannot find the corresponding page, it will throw a 404 to the browser
    . There is no such problem in the hash routing mode, because the hash routing judges the route based on the hash value and the hash value (#/login) will not be included in the http request, so there will be no impact on the server at all. In the process of page reloading,
    even if location/login is not configured, 404 will not appear

Solution: In history mode, configure nginx try_files $uri $url/ /index.html. That is, configure redirection so that the route is always directed to the index.html page, and the routing is fully handled by the front end

2. The process of vue template to generate html rendering

We know that <template></template> is a template, not real HTML. Browsers don’t recognize templates, so we need to compile it into native HTML that browsers recognize. The main process of this piece is as follows. The first step
, Extract the label elements (native html and non-native html), variables, attributes, etc. in the template by means of regularization, and parse them into an abstract syntax tree AST. The second step is to generate a render function after some processing, such as marking static nodes and other optimizations
.
The first step is to generate vnodes and virtual dom nodes through the render function.
The fourth step is to find out the vnodes that need to be rendered to the view through the patch process (diff algorithm-new and old virtual dom comparison). The fifth
step is to create real dom nodes (html) based on vnodes. ), render into the view, and complete the rendering of the template

3. Vue template compilation process

Template compilation is the 1-3 steps in the process of generating html

The first step is to extract the label elements, variables, attributes, etc. in the template through regularization and other means, and parse it into an abstract syntax tree AST (an object). The second step is to optimize the AST, traverse the AST and
mark the static nodes and static roots with the static attribute The third part of the node
is to generate the corresponding render function according to the AST

Four, diff algorithm

The diff algorithm is used in Vue to compare the generated new and old vnodes to optimize page rendering. After the comparison, only the changed DOM
features are rendered:

  1. Same-level comparison, not cross-level comparison. We all know that virtual dom and real dom are both tree structures, and it is more reasonable to compare vnodes at the same level
  2. The method of comparison is head-to-tail comparison (react is adjacent comparison)

Five, set global variables in vue3

  1. Use the config.globalProperties global object (Vue.prototype.xxx is used in vue2)
  2. Use provie/inject global injection

Six, vuex data persistence

  1. Use localStorage or sessionStorage
  2. Use the vue-along plug-in (essentially the localStorage or sessionStorage principle used, but the access process component completes it for us)

7. The difference between $router and $route in vue

$router is the instance object of router, through which the entire routing file and some instance methods can be obtained.
$route is the currently active routing information object, a read-only attribute object that cannot be monitored, and can obtain information about the currently active routing

Eight, the responsive principle of vue3, the realization of component v-model

Implement the v-model of the component:

// 父组件
<template>
  <Child  v-model="msg"></Child>
</template>
<script setup>
  const msg = ref('xxx')
</script>

// 子组件
<script setup>
defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>
<template>
  <div @click="emit('update:modelValue', 'xxxx')">{
   
   { modelValue }}</div>
</template>

In vue3, the parent component passes in the variable value through v-model, and the child component passes in the fixed parameter "modelValue" through defineProps to obtain the variable value of v-model in props, and then passes in the fixed identifier "update" through the first parameter of defineEmits :modelValue", the second parameter passes in the changed value to modify the value of v-model to realize the two-way binding of v-model
In vue2, the parent component passes in the variable value through v-model, and the child component gets it through this.props The value passed in by v-model, and trigger events such as input through $emit to modify the value of v-model to realize the two-way binding of v-model

Responsive principle of vue3:
There will be no responsive changes in ordinary js execution, and a series of processing is required. The general process is as follows
1. Create a side effect method, which is mainly used to perform changes, such as a variable value Change, the value of other variables related to its business is changed by executing side effects
2. Create a map (weakMap) or set (weakSet) data type to store the side effects that need to be executed
3. Create a method for collecting side effects
4. Create an execution The method corresponding to side effects
For example, the business logic of a, b, and c is a = b + c. To achieve a responsive effect, that is, when b and c change, the value of a also changes accordingly. You need to do the following

let a = 0, b = 0, c = 0
// 创建副作用
const effect = () => {
    
     a = b + c }
//创建一个set收集副作用
const effects = new Set()
// 创建一个收集副作用的方法
const addEffect = () => {
    
     effects.add(effect) }
addEffect()
// 创建一个执行副作用的方法
const deal = () => {
    
    
  effects.forEach(effect => {
    
     effect() })
}
b = 1
deal()
console.log(a) // 1

The above is a basic process for implementing responsiveness. The most critical point is to realize automatic collection of side effects and automatic execution of side effects. In vue: Vue2 monitors get
and set for a single property through the Object.defineProperty() method of es5, and performs data processing Hijacking, combined with the publish-subscribe model to implement
vue3 through the proxy API of es6 to monitor get and set for the entire object, and proxy objects. Then use reflect API reflection to operate on the properties of the proxied object. Compared
with:
proxy API has the following advantages:
1. Directly intercept objects for monitoring including arrays.
Object properties can save for in, closures and other content to improve efficiency (directly bind the entire object)
3. Can detect all operation behaviors of proxy objects Disadvantages: es6 syntax is not compatible with defineProperty
for some low-version browsers
Advantages: es5 syntax compatibility is good
Disadvantages:
1. Only a certain property can be monitored, not all objects, and only get and set can be monitored, and cannot be monitored when adding and deleting, need to use $set, $delete method To assist
2. The monitoring of the array type is intercepted by rewriting some instance methods of updating the array. There are obvious defects such as the inability to monitor and modify the subscript of the array. 3. Because only a single attribute of the monitoring
object can be processed recursively, so When the data is complex and deep, there will be performance problems that affect the initialization speed

9. Summary of the difference between vue2 and vue3

1. Statement cycle
In terms of statement cycle, vue3 uses setup instead of beforeCreated, created, and the others are roughly the same, except in different ways of use, such as mounted, vue3 uses the onMounted statement cycle hook function

2. Fragmentation (multiple root nodes)
The template in vue2 can only support a single root node, while vue3 supports multiple root nodes

3. Responsive principle
vue2: Object.defineProperty()
vue3: proxy + reflect

4. The support component is moved outside the root node of the app.
Vue3 provides the Teleport component to transfer the component outside the root node of the app, such as dialog

5. Packaging optimization
tree-shaking: the concept of module packaging webpack, rollup, etc., removes unused code in the js context, and mainly relies on the import and export statements in esmodule to detect whether the code module is exported, imported, and use.
For the support of tree-shaking in vue3, the global and internal APIs have been refactored, and the global can only be accessed using the named export built by the es module. Delete
unused code and dependencies, and optimize the size of the packaged file.

6. The writing style
vue3 uses a combined api, the taste of hooks, and vue2 uses an optional api

7. The method of declaring responsive variables
Vue3 uses reactive and ref to declare responsive variables. In vue2, the data method in the optional API returns an object for responsive binding.

8. Asynchronous component
vue3 provides a complete Suspense asynchronous component. It uses the #default slot to display the asynchronous content display. When the asynchronous unloading is completed, it will display the content in the #callback slot by default. Vue2 only proposes an experimental Suspense asynchronous
component , to understand whether to use

9. Event caching
After the first rendering of vue3, the bound events will be cached. I don’t want to bind new functions to events every time I render like vue2.

10. Virtual dom and diff algorithm optimization
The vnode object of vue3 adds a patchFlag field, which is used to mark dynamic text information, static nodes, etc. Static nodes are directly referenced during rendering without recreating. In the diff, static nodes and different types of dynamic nodes are distinguished according to the patchFlag field, which reduces the comparison of the nodes themselves and attributes to a certain extent.

10. Component parameter passing method

1. Props down, emit up
2. Use vuex to share store
3. Use event bus
4. $attrs and $listeners are instance attributes of Vue. When there is a slot in the subcomponent, use $attrs to distribute unknown attributes, similar to $attrs, and $listeners to distribute unknown events
5. $refs can directly access the internal data of subcomponents
6.provide/inject

11. Define a variable a = 1 in the vue component to display on the page, use the for loop to change the value of the variable 100 times, how many times the page will be rendered

Since Vue is a responsive framework, it will automatically update the DOM when the value of a changes, so when looping 100 times to change the value of a variable, the DOM
will re-render and update 100 times, so, in this specific example, the page will render 100 times (error)

Positive solution:
traversing 100 times depends on the length of time consumed, and the number of renderings is determined according to the length of time consumed.
Because if the responsive variable is changed 100 times within 1ms, the Vue interface will only be re-rendered once.

Vue uses an asynchronous update queue to handle data changes. When the data changes, Vue will add these changes to the asynchronous update queue. However, since JavaScript is single-threaded, the browser's refresh rate is usually 60Hz (60 times per second), so within 1ms, the browser can only refresh once.

When multiple updates are added to the asynchronous update queue, Vue will merge these updates before the next refresh cycle to reduce unnecessary re-rendering. This means multiple changes to reactive variables within 1ms and only the last change will trigger a re-render.

It should be noted that Vue will perform performance optimization according to specific situations. For example, for large amounts of data that changes frequently, Vue may use batch updates to process updates more efficiently. But the general principle is that in the same refresh cycle, Vue will only perform one re-render.

react-related

1. React style implementation scope

Use css modules css-in-js (styled-components)
<!-- import styles from './App.module.css'; -->
<!-- styles. Style name use -->

2. Component parameter passing method

1. Pass data through props
2. Share data through context
3.redux
4.eventbus

browser related

1. Why are basic data types stored on the stack and complex data types are stored on the heap

In javascript, the engine maintains the execution context state of the program through the stack space. If all data is stored in the stack space, it will affect the switching efficiency of the execution context, which will lead to the execution efficiency of the entire program. Therefore, data with large memory The type is stored on the heap, and only a pointer to the heap is marked on the stack

Two, js garbage collection mechanism

The garbage collection mechanism is the way to clean up memory

The memory allocation mechanism in js (according to the data type)
the basic data type is stored on the stack, and the reference data type is stored on the heap. The basic data type values ​​stored on the stack can be cleared directly through operations, while the data values ​​on the heap have an uncertain size and need to be processed by the garbage collection mechanism of the js engine.
For memory management on the heap, js is automatic. Whenever we When creating functions, objects, and arrays, the corresponding memory space will be automatically allocated. When the object is no longer referenced, it is garbage, and the object cannot be accessed from the root (reachable object) is also garbage.

Garbage collection strategy
1. Mark-clear
2. Reference counting

3. Redrawing and reflow (rearrangement)

The browser rendering process is mainly divided into three steps: dom parsing, css parsing, and layout drawing.
When the dom and css change and the page is re-rendered, the browser will layout (reflow) or draw (redraw) the changed part

Redrawing means that the style change of an element does not affect the position of the element in the document flow, and only needs to redraw the new style to the screen, such as changing the background color, font color, etc. Repainting does not change the size and position of the element

Reflow usually refers to changes in the geometric size, position, and layout of elements, which require recalculating the size and position of elements and rebuilding the rendering tree and layout tree. For example, the addition and deletion of elements, wh modification, and position, as well as element styles such as animations, etc. (transform conversion will not affect reflow), will cause reflow.

The following reasons will trigger the redrawing and reflow of the page: when
the page is initially rendered,
the size of the browser window changes and
the addition, deletion and modification of the scaling dom element
Any changes in the position, size, content, style, etc. of the element
in the css pseudo-class (:before:after)
The embedded iframe content changes

Optimization method:
1. To avoid operating multiple dom elements at one time, multiple operations should be combined into one operation, and documentFragment should be used to optimize a large number of dom operations.
2. To avoid frequently modifying the style of dom elements such as el.style.top, use Class or styles to complete the relevant operations only trigger a reflow or redraw
3. Avoid using table layout, the size of each cell depends on the content, and changes in the cell size may cause the entire table to be re-layouted.
4. Use flex layout instead of traditional layout
5. Try to use transform instead of top, left and other positioning
6. Try to keep animation elements out of the document flow to reduce the impact on other elements
7. For elements that need to be reflowed, first Element hides and reflows

4. Hardware acceleration (gpu acceleration)

Use CSS properties such as transform or opacity to enable GPU acceleration to process some animations

5. What will the browser do if a dom style modification is encountered when executing js synchronization code

When executing synchronous javascript code, the browser will wait for the execution of the javascript code to complete before updating the rendering of the page. If the code modifies the dom style, the change will not be updated to the browser window immediately. It is necessary to wait for the execution of the js code to redraw and render the entire document to directly render the interface to display the updated style.
Reason:
The js engine and the rendering engine in the browser are mutually exclusive, that is, the rendering engine (cpu) will be blocked when the js code is executed, and the browser will save the modification in the rendering queue when encountering a style modification in js, only When the execution of this js is completed, the rendering engine will start rendering the modified document

6. Browser multi-threading

Rendering engine thread, js engine (main thread), timing trigger thread, event trigger thread (task queue), http request thread, service worker

Seven, the composition of the browser

User interface - user interface content other than tab pages
Browser engine (data persistence layer) - used to transfer data between the user interface and the rendering engine Rendering
engine (including network request module, js parser, etc.) - rendering user requests The page content
rendering engine is the browser core, the browser core, blink used by Google, Edge and opera, and webkit used by safari

8. The process of entering the address in the browser address bar to obtain data

To be added

9. The process of rendering html to the page after entering the address in the browser address bar to obtain data (data to view)

1. Browser with multi-process structure
Process is the basic unit for resource allocation and scheduling by the operating system. It can apply for and own computer resources. Process is the basic execution entity of the program (occupying independent space). Thread is the operating system that can perform calculation scheduling
. The smallest unit, multiple threads can run concurrently in one process, and each thread executes different tasks in parallel (threads are resource shared)

When we start a program, a process will be created to execute the task code, and a memory space will be allocated for the process. The state of the application is stored in the memory space. When the application is closed, the memory will be deleted. Recycle. A process can start more processes to perform tasks. The memory space allocated by each process is independent. If data needs to be transmitted between two processes, it needs to be transmitted through the inter-process communication pipeline ipc.
Many applications have a multi-process structure, and the processes are independent of each other. This is to prevent one process from being stuck and affecting the entire application.
A process can divide tasks into more small tasks, and then create multiple threads to execute different tasks in parallel. Threads under the same process can directly communicate and share data

For previous single-threaded browsers, there are generally page threads responsible for page rendering and display, js threads to execute js codes, and threads with various other functions. The single-threaded structure will cause many problems. One is instability. If one thread is stuck, it may cause problems in the entire process. For example, if multiple tabs are opened, one of the tabs may be stuck, which may cause the entire browser to fail to operate normally. The second is unsafe. Single-process browsers (threads) can share data, and js threads can freely access all data in the browser process. The third is that it is not smooth. A process needs to be responsible for too many things, which will lead to operational efficiency problems. Therefore, in order to solve the above problems, a multi-process browser structure is implemented

Multi-process browsers are roughly divided into:
the browser process is responsible for controlling the user interface other than the tab page, including the address bar, bookmarks, forward and back buttons, etc., and is responsible for coordinating with other browser processes; the network process is responsible for initiating and accepting network requests
GPU
process Responsible for the rendering of the entire browser interface.
The renderer process
is used to control the rendering of page content. By default, the browser may create a process for each tab page (Google Chrome startup method - the process model can be configured)

Text:
When you enter an address in the address bar, the UI thread of the browser process will capture your input. If you visit a URL, the ui thread will start a network thread to request DNS for domain name resolution to obtain an IP address, and then start connecting to the server retrieve data. If the input content is not a URL but a string of keywords, the browser will use the search engine configured by default to query.
After the html data is successfully obtained, the browser executes the rendering process as follows:
1. When the network thread obtains the data, it will check whether the site is a malicious site through safeBrowsing (prompt that the current connection is not safe, and the browser blocks your access), safeBrowsing is Google A set of site security systems inside the browser, such as checking whether the ip is in the blacklist. When the returned data is ready and the security check is passed, the network thread will notify the UI thread, indicating that I am ready and it is your turn. Then the UI thread notifies the rendering process to render the page, and the browser process passes the data to the rendering process through the ipc pipeline to officially enter the rendering process. The core task of the renderer process is to render html, css, js, image and other resources into a web interface that users can interact with.

2. The main thread of the renderer process parses html to construct the dom data structure . The dom document object model is the browser's internal representation of the page, and it can interact with the data structure and api through js. The html is first tokenized by Tokeniser , and the input html content is parsed into multiple tags through lexical analysis, and the dom tree is constructed according to the recognized tags. During the construction of the dom tree, a document object is created, and the dom with documnet as the root node The tree is constantly being modified, adding various elements to it.

3. Some additional resources will be inserted into html, such as pictures, css, js scripts, etc. These resources need to be downloaded through the network or loaded directly from the browser cache. Images and css resources will not block the parsing of HTML, so they will not affect the generation of DOM. However, when a script tag is encountered during the html parsing process, the html parsing process will be stopped and the js code will be loaded and parsed and executed (because there may be some modifications to the dom in the js, such as document.write will be called after the page is loaded. cover the entire html page)

4. A dom tree is obtained after parsing the html , but the style of each node of the dom tree is not known at this time. The main thread needs to parse css and determine the calculation style of each dom node , even if no css style is provided, the browser has its own default style. After the style analysis is completed, the dom structure and the style of each node are known at this time.

5. Next, you need to know where each node needs to be placed on the page, that is, the coordinates of the node and how much area the node needs to occupy . This stage is called layout layout . The main thread generates the layout tree by traversing the dom and the calculated style. Each node on the layout tree records x, y coordinates and frame size. It should be noted that the dom tree and the layout tree are not in one-to-one correspondence. Nodes with display:none set will not appear on the layout tree, but content worth elements are added to the pseudo-class element, and the content in the content will appear in the The layout tree will not appear in the dom tree. This is because the dom tree is obtained through html parsing and does not care about the style, while the layout tree is generated based on the dom tree and the calculated style. The layout tree corresponds to the node that is finally displayed on the screen

5. After getting the layout tree, you need to know the order in which the nodes are drawn on the page. For example, the z-index in the style will affect the hierarchical relationship of node drawing. If we draw the page according to the hierarchical structure of the dom, it will lead to errors render. Therefore, in order to ensure that the correct level is displayed on the screen, the main thread traverses the layout tree to create a drawing record table to record the order in which nodes are drawn. This stage is called drawing .

6. At this point, the parsing process of the rendering process is completed, and the next step is to convert the parsed information into pixels and display them on the screen. This behavior is called rasterization-rasterization refers to converting the tiles into bitmap . A very simple way that chrome first used was to rasterize only the content of the user-accessible area. When the user scrolls the page, more content is rasterized to fill it, which will cause a delay in page display. A more complex rasterization process that chrome now uses is called compositing , compositing is a method of layering parts of the page into multiple layers, rasterizing them separately, and compositing them separately in the compositor thread Actions on the page. To put it simply, all elements of the page are layered according to certain rules, and the layers are rasterized, and then only the content of the visible area is combined into a frame for display to the user. The main thread traverses the layout tree to generate a layer
tree , when the layer tree is generated and the drawing order is determined, the main thread passes this information to the compositor thread, and the compositor thread rasterizes each layer. Since one layer may be as large as the entire length of the page, the compositor thread Divide them into tiles, then send each tile to the rasterizer thread, which rasterizes the tiles and stores them in GPU memory.

7. When the tile rasterization is completed, the compositor thread will collect tile information called "draw quads", which records the location of the tile in memory and the location information drawn on the page. Based on these information, the synthesizer thread generates a synthesizer frame, and then the synthesizer frame is transmitted to the browser process through IPC, and then the browser process transmits the synthesizer frame to the GPU, and then the GPU renders and displays it on the screen.

8. At this point, you can see the display of the content on the page.

When scrolling the page or operating some interactions that change the page, a new compositor frame will be generated, and the new frame will be passed to the GPU for rendering on the screen

Brief summary:
After the network thread in the browser process requests to obtain the html data, it passes the data to the main thread of the renderer process through IPC. The main thread parses the html to construct a dom tree, and then performs style calculations. According to the dom and the calculated The style generates a layout tree (layout tree), generates a drawing order table by traversing the layout tree, and then traverses the layout tree to generate a layer tree, and then the main thread passes the layer tree and drawing order information to the compositor thread, and the compositor thread proceeds according to the rules Divide the layer, and divide the layer into smaller tiles and pass it to the rasterization thread for rasterization. After the rasterization is completed, the compositor thread will get the "draw quads" tile information passed by the rasterization thread According to these information, a synthesizer frame is synthesized on the synthesizer thread, and then the synthesizer frame is sent back to the browser process through IPC, and the browser process is then passed to the GPU for rendering on the page

Rearrangement (reflow) and redrawing
When we change the size and position attributes of an element, the calculation style, layout, drawing and all subsequent processes will be re-performed. This behavior is reflow (reflow).
When we change the color property of an element, the layout will not be retriggered, but the style calculation and drawing will still be triggered. This is redrawing.
Both rearrangement and redrawing will occupy the main thread. At the same time, js is also running on the main thread, and there will be a problem of preempting time ( js engine and rendering engine are mutually exclusive ). If you write an animation that keeps redrawing and rearranging, the browser needs to run style calculation layout and drawing operations every frame. We know that when the page refreshes at a rate of 60 frames per second (16ms per frame), it will not It will make the user feel that the page is stuck. If there are still a lot of js tasks to be executed when running the animation, because the style calculation, layout, drawing, and js execution are all executed on the main thread, when the layout and drawing are completed within one frame, there is still time left for js You will get the right to use the main thread. If the execution time of js is too long, js will not be returned to the main thread in time at the beginning of the next frame, resulting in the next frame of animation not being rendered on time, and the page animation will be stuck.

Optimization methods:
1. Use the requestAnimationFrame() method
The requestAnimationFrame() method is an API provided by the browser for running animations through JavaScript. Compared with using the setTimeout timer for animation operations, the performance of requestAnimationFrame is more optimized. Because it can follow the refresh rate of the display, it will be called every frame instead of running the code at a fixed time interval. When
the page is inactive, that is, when you do not come to the current page, requestAnimationFrame will not be executed.
If we want to stop requestAnimationFrame, we need to use cancelAnimationFrame method
2. Through the above rendering process, we can see that the whole process of rasterization does not occupy the main thread (compositor thread and rasterization thread run separately), which means It does not need to compete with js for the main thread, and may cause the page to drop frames when redrawing and rearranging repeatedly. This is because js execution may block the main thread. There is an animation property in css -transform (conversion), through which The implemented animation will not go through layout and drawing, but run directly in the compositor thread and rasterization thread, so it will not be affected by the execution of js in the main thread. More importantly, the animation implemented through transform saves a lot of computing time because it does not need to go through operations such as layout drawing style calculations. By layering elements and using hardware acceleration (the industry calls GPU hardware acceleration, you can also use the opacity attribute to achieve acceleration)

10. v8 engine executes js code

javascript dynamic type language, js engine uses runtime compilation to compile js code (just in time compilation is referred to as JIT; static type language uses AOT to compile ahead of time). The function of the js engine is to compile the js code into code that the machine can recognize.

The v8 engine is a c++ program that receives javascript code, compiles the code and then executes it. The compiled code can run on various operating systems and processors.
Mainly responsible for: compiling and executing js code, processing call stack, memory allocation, garbage collection, etc.

A general js engine will use three important components in compiling and executing code - parser (parser), interpreter (interpreter), compiler (compiler). The parser is responsible for parsing js code
into an abstract syntax tree AST The interpreter is responsible for interpreting the ast abstract syntax tree into bytecode bytecode. The interpreter also has the ability to directly interpret and execute bytecode. The compiler is responsible for compiling bytecode into machine code that runs more efficiently.

The latest version of the v8 engine executes the js code process (the overall architecture mode is the coexistence of bytecode and optimized machine code)

1. Parse js code through parser to generate abstract syntax tree
2. AST generates bytecode bytecode through ignition benchmark interpreter. At this time, ast will be cleared to release memory space. The generated bytecode is directly executed by the interpreter, and the generated bytecode It will be used as a benchmark execution model. During continuous execution, the interpreter will collect a lot of information that can be used to optimize the code, such as the type of variables and which functions are executed frequently. These information are sent to the compiler
3.v8 engine's new compiler Turbofan to compile optimized machine code based on the information collected by the interpreter and the bytecode. During the continuous execution of bytecode, more machine code may be generated.
4. There is a case of reverse reduction into bytecode (deoptimization). This is because js is a dynamic language, which will cause the interpreter (ignition) to collect errors. Information, such as a sum method as follows

function sum(a, b) {
    
    
    return a + b
}

The js engine does not know what type the parameters a and b are when the function is declared. When the sum method is called multiple times and two integer integers are passed in, sum will be marked as a hot function by the interpreter, and the interpreter will send the collected type information and the bytecode corresponding to the function to the compiler, and the compiler will generate In the optimized machine code, it is assumed that the parameter of the sum function is int type, and when this function is called later, only the faster machine code is used. But if we call the sum method to pass in two strings at this time, the machine code does not know how to process the parameters of the strings. At this time, deoptimization is required to fall back to bytecode, which is interpreted and executed by the interpreter. Therefore, try not to change the type of a variable during the programming process, and it is best to keep the parameters passed into the function fixed, otherwise it will have some impact on the v8 engine and lose certain performance.

Some optimization strategies for the v8 engine to process js code:
1. If the function is only declared but not called, it will not be parsed into AST and bytecode will not be generated.
2. The function is called only once, and the bytecode is directly interpreted and executed without optimized compilation.
3. If the function is called multiple times, it may be marked as a hot function and may be compiled into machine code

Note - bytecode generation is much faster than compiling to machine code

11. SSR server rendering, CSR client rendering and SSG pre-rendering

to be completed

SSR purpose:
1. Solve the slow loading of the first screen
2. Optimize the SEO search engine of single page application (SPA)

Isomorphic: A set of code needs to run on the client and also on the server

vue: Nuxt.js
react: Next.js
native node service to build ssr, mainly to configure webpack to recognize react and vue syntax, such as .jsx, .vue, etc.

Water injection and dehydration operation
renderToString method

Build tools such as webpack

1. The entire hot update process of Vite

1. Create websocket server and client files, start the service
2. Monitor file changes through chokidar
3. When the code changes, the server will make a judgment and push it to the client
4. The client will perform an update operation based on the pushed information

Two, vite understanding

vite is a new-generation build tool based on esbuild and rollup, relying on the browser's own ESM compilation function to achieve the ultimate development experience

webpakc build tool
The general running process (packaging) of the build tool: Grab-compile-build the code of the entire application, and generate a compiled and optimized production environment code that is well compatible with various browsers. The process in the development environment is also roughly the same,
first Build and package the entire application, and deliver the packaged code to the dev server to run. With the complexity of the front-end business, the amount of js code increases exponentially, resulting in longer and longer packaging and building time. In the dev server, the server startup and hot update have reached the performance bottleneck, and there is no room for optimization.
vite is produced under this prospect

Compared with webpack, vite has the ultimate development experience. In the dev server, webpack adopts the method of first building and packaging the entire application, and then handing over the packaged code to the dev server to run. Vite, on the other hand, directly delivers the source code to the browser, enabling the dev server to open in seconds. The browser needs relevant modules to initiate a request to the dev server, and the server returns the corresponding modules to the browser, realizing true on-demand loading.

Vite focuses on the ultimate experience in the development environment, and integrates Rollup in the production environment

Highly integrated, ready to use out of the box;
rapid hot update based on ESM, no need to package and compile
Dependency preprocessing based on esbuild
Compatible with Rollup's huge plug-in mechanism, plug-in development is more concise
Naturally supports TS

3. The role of webpack loader

Webpack loaders are special modules that process non-JS files imported into your application and convert them into valid modules recognized by Webpack. Used to support CSS, images, JSON, XML and other resource loading
For example: style-loader and css-loader: style-loader and css-loader are often used together to load and process CSS files.
css-loader: Read CSS files and let Webpack parse them into JS module export code blocks.
style-loader: Receive the JS module exported by the css-loader module and insert it into the DOM as a style tag

Fourth, webpack in-depth (optimization, use)

to be completed

Front-end unit tests

jest uses

to be completed

Guess you like

Origin blog.csdn.net/weixin_42508580/article/details/129797148