Front end 30 Q: May you be able to stand at thirty

insert image description here

Foreword:

      Gold three silver four, if you are going through work adjustment, then I suggest you must bookmark it, this is an essential guide to prevent the cold winter of the Internet ~

1. What is the output result? How to change the output result of cycle 1 to the print result of cycle 2

for(var i = 0;i<5;i++){
    
    
  setTimeout(()=>{
    
    
    console.log(i) //五次5
  },1000)
  console.log(i) //0 1 2 3 4
}
for(let i = 0;i<5;i++){
    
    
  setTimeout(()=>{
    
    
    console.log(i) // 0 1 2 3 4
  },1000)
}
// 改变
for(var i = 0;i<5;i++){
    
    
  (function(j) {
    
    
      setTimeout( function timer() {
    
    
          console.log( j );
      }, j*1000 );
  })(i);
}

      This is because setTimeout is executed asynchronously. SetTimeout is executed once in each for loop, but the functions inside are not executed, but are placed in the task queue for execution. The tasks in the task queue will be executed only after the tasks on the main line are executed. That is to say, it will wait until the for loop has finished running before executing the fun function, but when the for loop ends, the value of i has changed to 5, so although the timer runs for 5 seconds, the content on the console Still 5.
At the same time, because the let at the head of the for loop not only binds i to the for loop, in fact it rebinds it to each iteration of the loop body, ensuring that the value at the end of the previous iteration is reassigned. The function() in setTimeout belongs to a new domain. The variable defined by var cannot be passed into the function execution domain. By using let to declare the block variable can act on this block, so the function can use the variable i The parameter scope of this anonymous function is different from the scope of the for parameter, which is done by taking advantage of this point. The scope of this anonymous function is somewhat similar to the attributes of a class, which can be used by inner methods.
Finally, variables declared using var will have the problem of variable promotion, while using let will not have the problem of variable promotion. If you have to use var as the loop header, the printed result after the loop is exactly the same, you can use the method of passing parameters or closure

2. What are the array loop methods?

(1), forEach: it will traverse the array, there is no return value, it is not allowed to write return in the loop body, it will change the content of the original array. forEach() can also loop the object (2), map: traverse the array, it will return a new
array , will not change the contents of the original array
(3), filter: will filter out elements in the array that do not meet the conditions, and put the elements that meet the conditions into a new array without changing the original array
(4), reduce:

let array = [1, 2, 3, 4];
let temp = array.reduce((x, y) => {
    
    
	console.log("x,"+x);
	console.log("y,"+y);
	console.log("x+y,",Number(x)+Number(y));
	return x + y;
});
console.log(temp);  // 10
console.log(array);  // [1, 2, 3, 4]

(5), every: traverse the array, if each item is true, return true, as long as one is false, return false
(6), some: traverse each item of the array, if one returns true, stop the loop

3. What is the difference between defer and async in the script tag?

defer : After the script is loaded asynchronously, it will not be executed immediately, but will not be executed until the entire page is normally rendered in memory. Multiple defer scripts will be loaded in the order they appear on the page.
async : It also loads scripts asynchronously, the difference is that the scripts are executed immediately after loading, which causes the scripts under the async attribute to be out of order, which is not applicable to the case where scripts have sequential dependencies.

4. What is the difference between using the setTimeout() method to simulate setInterval() and setInterval()?

      First look at the flaws of setInterval, the timer created using setInterval() ensures that the timer code is inserted into the queue regularly. The problem with this approach is that if the timer code doesn't finish executing before the code is added to the queue again, the result is that the timer code runs several times in a row with no gaps in between.

      Therefore, the following situation may occur: the current execution stack takes a long time to execute, resulting in the accumulation of events added by multiple timers in the event queue. When the execution stack ends, these events will be executed in sequence without any pause in between, which cannot be achieved. The effect of executing at intervals.

      Fortunately though: javascript engines are smart enough to avoid this problem. When using setInterval(), the timer code is only added to the queue if there are no other code instances for that timer. This ensures that the timer code enqueues the minimum interval for the specified time. There are two problems with this repeating timer rule:

1. Some intervals will be skipped;

2. The code execution time of multiple timers may be smaller than expected;

eg: Suppose, an onclick event handler uses the setInterval() to set a 200ms repeat timer.
If the event handler takes a little over 300ms to complete.
insert image description here


       Note: The first timer in this example is added to the queue at 205ms, but cannot be executed until 300ms has elapsed. When the timer code is executed, another copy is added to the queue at 405ms. At the next interval, at 605ms, the first timer code is still running while there is already an instance of the timer code in the queue. As a result, the timer code at this point in time will not be added to the queue. As a result, after the timer code added at 5ms ends, the timer code added at 405ms is executed immediately

       So if you use setTimeout instead, you can ensure that only after one event ends, the next timer event will be triggered. This ensures that the timer code enqueues the minimum interval at the specified interval.
Here are 2 easy ways to do it:

function say(){
    
     
  //something 
  setTimeout(say,200); 
}
setTimeout(say,200) 

// 或者

setTimeout(function(){
    
     
  //do something 
  setTimeout(arguments.callee,200); 
},200); 

5. How does JS control the loading of one picture at a time, and then load the next picture after loading

(1) Method 1

<script type="text/javascript"> 
  var obj=new Image(); 
	obj.src="http://www.phpernote.com/uploadfiles/editor/201107240502201179.jpg"; 
	obj.onload=function(){
    
     
  	alert('图片的宽度为:'+obj.width+';图片的高度为:'+obj.height); 
  	document.getElementById("mypic").innnerHTML="<img src='"+this.src+"' />"; 
	}
</script> 

<div id="mypic">onloading……</div> 

(2) Method 2

<script type="text/javascript"> 
  var obj=new Image(); 
	obj.src="http://www.phpernote.com/uploadfiles/editor/201107240502201179.jpg"; 
	obj.onreadystatechange=function(){
    
     
  if(this.readyState=="complete"){
    
     
    alert('图片的宽度为:'+obj.width+';图片的高度为:'+obj.height); 
    document.getElementById("mypic").innnerHTML="<img src='"+this.src+"' />"; 
    }
  }
</script> 

  <div id="mypic">onloading……</div> 

6. How to achieve the effect of sleep (es5 or es6)

(1) The way of while loop

function sleep(ms){
    
     
  var start=Date.now(),expire=start+ms; 
  while(Date.now()<expire); 
  console.log('1111'); 
  return; 
}

After executing sleep(1000), 1111 is output after sleeping for 1000ms. The disadvantage of the above-mentioned circulation method is obvious, and it is easy to cause an endless loop.
(2) Realized by promise

function sleep(ms){
    
     
  var temple=new Promise( 
    (resolve)=>{
    
     
      console.log(111);
      setTimeout(resolve,ms);
    }); 
  return temple 
}

sleep(500).then(
  function(){
    
    
    //console.log(222) 
})

//Output 111 first, then output 222 after a delay of 500ms
(3) Encapsulated by async

function sleep(ms){
    
     
  return new Promise((resolve)=>setTimeout(resolve,ms)); 
}
async function test(){
    
     
  var temple=await sleep(1000); 
  console.log(1111) 
  return temple 
}
test(); 

//Delay 1000ms and output 1111
(4). Realized by generate

function* sleep(ms){
    
     
  yield new Promise(function(resolve,reject){
    
     
    console.log(111); 
    setTimeout(resolve,ms); 
  })
}

sleep(500).next().value.then(
  function(){
    
    
    console.log(2222)
}) 

7. Realize deep cloning of all objects in JS (wrapper object, Date object, regular object)

       Deep cloning of objects can be easily realized through recursion, but whether this method is implemented in ES6 or ES5, it has the same defect, that is, it can only realize deep copying of specific objects (such as arrays and functions), and cannot realize the packaging object Number. Copy of String, Boolean, and Date objects, RegExp objects.
(1) The previous method

function deepClone(obj){
    
     
  var newObj= obj instanceof Array?[]:{
    
    }; 
  for(var i in obj){
    
     
    newObj[i] = typeof obj[i] == 'object' ? deepClone(obj[i]):obj[i]; 
  }
  return newObj; 
}

This method can realize the cloning of general objects and array objects, such as:

var arr=[1,2,3]; 
var newArr=deepClone(arr); 
// newArr->[1,2,3] 
var obj={
    
     
  x:1, 
  y:2 
}
var newObj=deepClone(obj); 
// newObj={x:1,y:2} 

But it is not possible to realize the cloning of packaging objects such as Number, String, Boolean, and regular objects RegExp and Date objects
, such as:

//Number 包装对象 
var num=new Number(1); 
typeof num // "object" 
var newNum=deepClone(num); 
//newNum -> {} 空对象 

//String 包装对象 
var str=new String("hello"); 
typeof str //"object" 
var newStr=deepClone(str); 
//newStr-> {0:'h',1:'e',2:'l',3:'l',4:'o'}; 

//Boolean 包装对象 
var bol=new Boolean(true); 
typeof bol //"object" 
var newBol=deepClone(bol); 
// newBol ->{} 空对象  

(2) valueof() function

       All objects have a valueOf method. The valueOf method is for: if there is any original value, it will convert the object to the original value representing it by default. Objects are compound values, and most objects cannot really be represented as a primitive value, so the default valueOf() method simply returns the object itself, rather than returning a primitive value. Arrays, functions, and regular expressions simply inherit this default method, and calling the valueOf() method on instances of these types simply returns the object itself.
For primitive values ​​or wrapper classes:

function baseClone(base){
    
     
  return base.valueOf(); 
}

//Number 
var num=new Number(1); 
var newNum=baseClone(num); 
//newNum->1 

//String 
var str=new String('hello'); 
var newStr=baseClone(str); 
// newStr->"hello" 

//Boolean 
var bol=new Boolean(true); 
var newBol=baseClone(bol); 
//newBol-> true 

In fact, for packaging classes, you can use the = sign to clone. In fact, there is no such thing as deep cloning. Here, valueOf is used to implement it, which is more grammatically compliant.
For the Date type:
Because of the valueOf method, the valueOf() method defined by the Date class will return its internal representation: the number of milliseconds since January 1, 1970. Therefore, we can define the clone method on the Date prototype:

Date.prototype.clone=function(){
    
     
  return new Date(this.valueOf()); 
}
var date=new Date('2010'); 
var newDate=date.clone(); 
// newDate-> Fri Jan 01 2010 08:00:00 GMT+0800 

For the regular object RegExp:

RegExp.prototype.clone = function() {
    
     
  var pattern = this.valueOf(); 
  var flags = ''; 
  flags += pattern.global ? 'g' : ''; 
  flags += pattern.ignoreCase ? 'i' : ''; 
  flags += pattern.multiline ? 'm' : ''; 
  return new RegExp(pattern.source, flags); 
};
var reg=new RegExp('/111/'); 
var newReg=reg.clone(); 
//newReg-> /\/111\// 

8. JS listens for changes in object properties

We assume that there is a user object here,
(1) In ES5, Object.defineProperty can be used to realize the monitoring of existing properties

Object.defineProperty(user,'name',{
    
     
	setfunction(key,value){
    
    }
})
//缺点:如果 id 不在 user 对象中,则不能监听 id 的变化

(2) In ES6, it can be realized through Proxy

var user = new Proxy({
    
    }{
    
     
	setfunction(target,key,value,receiver){
    
    }
})
//这样即使有属性在 user 中不存在,通过 user.id 来定义也同样可以这样监听这个属性的变化 

9. Why use Proxy API instead of defineProperty API in Vue3.0?

A: Responsive optimization.
(1) The biggest reason for the limitation of the defineProperty API is that it can only monitor singleton properties.
The responsive implementation in Vue2.x is based on the descriptor in defineProperty. It traverses + recurses the attributes in data, and sets getters and setters for each attribute.
This is why Vue can only respond to predefined attributes in data. Using subscripts in Vue to directly modify the value of an attribute or add a pre-existing object attribute cannot be monitored by a setter. This is a limitation of defineProperty.
(2) The monitoring of the Proxy API is aimed at an object, which can completely proxy all attributes.
Proxy API listens to an object, then all operations on this object will enter the monitoring operation, so that all attributes can be fully proxied. It can be understood that a layer of "interception" is set up before the target object, and external access to the object must be Through this layer of interception first, a mechanism is provided to filter and rewrite external access, which brings great performance improvement and better code.
(3) Responsiveness is lazy
In Vue.js 2.x, for an object with deep property nesting, if you want to hijack its deep internal changes, you need to recursively traverse the object and execute Object.defineProperty to convert each layer Object data becomes responsive, which will undoubtedly consume a lot of performance.
In Vue.js 3.0, using the Proxy API cannot monitor the deep-level property changes inside the object, so its processing method is to recursively respond in the getter. The advantage of this is that the internal properties that are actually accessed will become Responsive, simply can be said to be responsive on demand, reducing performance consumption.

10. Understanding of macro tasks, micro tasks, and cycle mechanisms in js

js belongs to single thread, which is divided into synchronous and asynchronous. js code is executed from top to bottom. Synchronous tasks are executed immediately in the main thread, such as simple logical operations and functions, while asynchronous tasks will not be executed immediately, but will be moved Steps are placed in an asynchronous queue, such as ajax, promise, event, timer, etc.
Execute synchronization first, and then execute again in asynchronous order after the main thread ends.
Event cycle: The synchronous task enters the main thread and executes immediately. After execution, the asynchronous task enters the main thread, and this cycle occurs.
In the event loop, each cycle operation is called tick, and the task processing model of tick is relatively complicated. There are two words in it: Macro Task (macro task) and Micro Task (micro task) macro task and micro
task (Execute micro-tasks first, then macro-tasks)
For js
macro-tasks: setTimeOut, setTimeInterval, postMessage
Micro-tasks: Promise.then
Focus: Promise synchronous Promise.then asynchronous

console.log("开始111");

setTimeout(function() {
    
    

  console.log("setTimeout111");

}, 0);

Promise.resolve().then(function() {
    
    

  console.log("promise111");

}).then(function() {
    
    

  console.log("promise222");

});

console.log("开始222");

Let's analyze it according to the steps:
1. When encountering a synchronization task, print "Start 111" first.
2. When encountering an asynchronous setTimeout, put it in the queue to wait for execution.
3. When a Promise is encountered, put it in the waiting queue.
4. When encountering a synchronization task, directly print "Start 222".
5. After synchronous execution, return to the code in the execution queue and execute it from top to bottom. If there are macro task setTimeout and micro task Promise, execute the micro task first, and then execute the macro task.
So the order of printing is: start111, start222, promise111, promise222, setTimeout111.

11. rgb and hexadecimal color conversion

First of all, we need to know the relationship between RGB and hexadecimal. For example, our most common white RGB is expressed as rgb(255, 255, 255), and hexadecimal is expressed as #FFFFFFF. We can put the hexadecimal color Except for '#', it is divided into two parts, that is, FF, FF, FF. How much is the hexadecimal FF converted to decimal? That's right, it's 255!

After understanding the relationship between hexadecimal and RGB, we will find that the method of converting RGB to hexadecimal is very simple

Convert the 3 RGB values ​​into hexadecimal numbers, and then concatenate them, that is, rgb(255, 255, 255) => '#' + 'FF' + 'FF' + 'FF'.
Clever use of left shift, we treat the hexadecimal value part as an integer, namely FFFFFF, we can understand it as FF0000 + FF00 + FF, as we explained above, if the left shift is based on hexadecimal calculation, it can be understood It is FF << 4, FF << 2, FF, but in fact, when we convert it to binary, it becomes FF << 16, as follows:

x * 16^4 = x * 2 ^ 16

After understanding the principle, the code is as follows:

function RGBFUN(rgb){
    
    
    // 取出rgb中的数值
    let arr = rgb.match(/\d+/g);
    console.log(arr,'输出rgb转换数值') //[ '0', '255', '0' ] 输出rgb转换数值
    if (!arr || arr.length !== 3) {
    
    
        console.error('rgb数值不合法');
        return
    }
    let hex = (arr[0]<<16 | arr[1]<<8 | arr[2]).toString(16);
    // 自动补全第一位
    if (hex.length < 6) {
    
    
        hex = '0' + hex;
    }
    console.log(`#${
      
      hex}`,'输出转换之后的数值') // #0ff00 输出转换之后的数值
    return `#${
      
      hex}`;
}
RGBFUN('rgb(0,255,0)')

12. JavaScript bit operation: when the corresponding bit of the two operands has one and only one 1, the result is 1, otherwise it is 0

Simple encryption can be achieved

const value = 456;
function encryption(str) {
    
    
    let s = '';
    str.split('').map(item => {
    
    
    s += handle(item);
    })
    return s;
}

function decryption(str) {
    
    
let s = '';
str.split('').map(item => {
    
    
    s += handle(item);
})
return s;
}

function handle(str) {
    
    
    if (/\d/.test(str)) {
    
    
    return str ^ value;
    } else {
    
    
    let code = str.charCodeAt();
    let newCode = code ^ value;
    return String.fromCharCode(newCode);
    }
}

let init = 'JS 掌握 位运算';
let result = encryption(init);             // ƂƛǨ扄戩Ǩ亅踘穟 加密之后
console.log(result,'加密之后')
let decodeResult = decryption(result);     // JS 掌握 位运算 解密之后
console.log(decodeResult,'解密之后')

13. [Based on webpack] What Loaders are there? Which ones have you used?

document

  • val-loader : executes code as a module and exports it as JS code
  • ref-loader : used to manually establish dependencies between files

JSON

  • cson-loader : load and convert CSON files

syntax transformation

  • babel-loader : Load ES2015+ code with Babel and transpile it to ES5
  • esbuild-loader : load ES2015+ code and use esbuild to transpile to ES6+
  • buble-loader : Load ES2015+ code with Bublé and transpile it to ES5
  • traceur-loader : Use Traceur to load ES2015+ code and convert it to ES5
  • ts-loader : Load TypeScript 2.0+ like JavaScript
  • coffee-loader : Load CoffeeScript like JavaScript
  • fengari-loader : load Lua code with fengari
  • elm-webpack-loader : Load Elm like JavaScript

template

  • html-loader : To export HTML as a string, you need to pass in the reference path of the static resource
  • pug-loader : loads Pug and Jade templates and returns a function
  • markdown-loader : compiles Markdown to HTML
  • react-markdown-loader : Compiles Markdown to React components using the markdown-parse parser
  • posthtml-loader : load and convert HTML files using PostHTML
  • handlebars-loader : compiles Handlebars files to HTML
  • markup-inline-loader : Inline SVG/MathML files into HTML. This is useful when applying icon fonts or CSS animations to SVGs.
  • twig-loader : compiles Twig templates and returns a function
  • remark-loader : load markdown through remark, and support parsing images in the content

style

  • style-loader : Add the content exported by the module as a style and add it to the DOM
  • css-loader : load CSS files and parse imported CSS files, and finally return CSS code
  • less-loader : load and compile LESS files
  • sass-loader : load and compile SASS/SCSS files
  • postcss-loader : Load and transform CSS/SSS files using PostCSS
  • stylus-loader : load and compile Stylus files

frame

  • vue-loader : load and compile Vue components
  • angular2-template-loader : load and compile Angular components

14. Talk about how Js implements inheritance?

1. Prototype chain inheritance: use the instance of the parent class as the prototype of the subclass.
Advantages:
1. Simple and easy to implement
2. The parent class adds new prototype methods and prototype attributes, and subclasses can access them.
Disadvantages:
1. Cannot implement multiple inheritance , because the prototype can only be changed by one instance at a time
2. All properties from the prototype object are shared by all instances (the color property in the appeal example)
3. When creating a subclass instance, parameters cannot be passed to the parent constructor


2. Constructor inheritance : Copy the instance attributes of the parent class to the subclass
Advantages:
1. Solve the problem that the subclass instance shares the reference attribute of the parent class in the prototype chain inheritance
2. When creating a subclass instance, parameters can be passed to the parent class
3. Multiple inheritance can be realized (call multiple parent class objects)
Disadvantages:
1. The instance is not an instance of the parent class, but an instance of the subclass
2. It can only inherit the properties and methods of the parent class instance, but cannot inherit the properties and methods of its prototype
3. Cannot To achieve function reuse, each subclass has a copy of the instance function of the parent class, which affects performance.


3. Combined inheritance (classic inheritance): Combine the prototype chain and the technology of borrowing constructors. Use the prototype chain to realize the inheritance of prototype properties and methods, and use the constructor to realize the inheritance of instance properties.
Advantages:
1. Make up for the shortcomings of construction inheritance. Now you can inherit both instance properties and methods and prototype properties. And method
2. It is both an instance of the subclass and an instance of the parent class
3. It can pass parameters to the parent class
4. The function can be reused
Disadvantages:
1. The parent class constructor is called twice, and two instances are generated
2. The constructor points to question 4. Instance inheritance: add new features


to the parent class instance and return it as a subclass instance . Disadvantages : 1. The instance is an instance of the parent class, not an instance of the subclass 2. Does not support multiple inheritance 5. Copy inheritance: copy the methods and properties in the parent class instance to the prototype of the subclass Advantages: 1. Support Disadvantages of multiple inheritance : 1. Low efficiency, poor performance, and high memory usage (because the properties of the parent class need to be copied) 2. Unable to obtain non-enumerable methods of the parent class (non-enumerable methods cannot be accessed using for-in) 6 .Parasitic combination inheritance: Through the parasitic method, the instance attributes of the parent class are cut off, which avoids the disadvantage of generating two instances through combination inheritance. Advantages : 1. Relatively perfect (JS is the preferred way to implement inheritance) Disadvantages: 1. It is more complicated to implement (can be implemented) Simplified by Object.create) 7.es6–Class inheritance: use extends to indicate which parent class it inherits from, and super must be called in the subclass constructor Advantages: 1. The syntax is simple and easy to understand, and the operation is more convenient Disadvantages: 1. Not All browsers support the class keyword lass Per





























15. What will be the output of the final result?

var length = 10;
function fn(){
    
    
    console.log(this.length)
}
var obj = {
    
    
    length: 5,
    method: function(fn){
    
    
        fn();
        arguments[0]()
    }
}
obj.method(fn,1)			//10  2

Analysis:
1. fn() : If a non-arrow function is nested in any function, at this time, if this in the nested function is not specified, it should point to the window object, so executing fn here will print window .length . If you use let to declare a variable, it will form a block-level action, and there is no variable promotion; while var has a declaration promotion. So the output result is 10; but if let length = 10 ; then the output result is: 0 2.
2. arguments 0 : In a method call (if the attribute of an object is a function, this attribute is called a method, and calling this attribute is called a method call), when the function body is executed, the object and array as the attribute access subject will be is the pointer of this in its calling method. (In layman's terms, whoever calls the method this points to).
Here arguments 0 is used as the attribute [0] of the arguments object to call fn, so this in fn points to the object arguments of the attribute access subject.
One more thing to note here is that the arguments parameter refers to all the actual parameters of the function and has nothing to do with the formal parameters. That is, when the function is called, the actual parameters passed in, fn and 1 are stored in the arguments object as a parameter, so the length of arguments is 2, so 2 is output.

16. How to implement CLI to create template projects?

Describe the basic steps of implementation:

  1. Terminal parameter analysis
  2. CLI interactively collects the necessary parameters to create a project
  3. copy template project
  4. Rewrite the package.json file (modify the project name, etc.)
  5. Prompt or execute the initialization process of the project after creation is complete
  6. Notes about the implementation process:
  7. The naming convention of name in package.json
  8. When a project with the same name is created again, it needs to consider whether it is overwritten or interrupted. In the case of overwriting, it needs to consider whether the created project is connected to the version management
  9. After the creation is complete, the prompt or execution of project initialization should be judged according to the package manager when using it.
  10. content expansion
  11. The interactive collection of parameters in the CLI can support historical project templates or third-party templates, and achieve compatibility through the creation of corresponding templates
  12. To create a project with the CLI, you usually need to execute the command to install the CLI first, and then run the built-in command to create the project in two steps. You can consider using the naming convention to directly execute npm create xxx, yarn create xxx to start the CLI to create the project

17. How to realize automatic tracking?

Automated burying can use Babel + custom burying plug-ins to automate function instrumentation during project compilation. There are two points to pay attention to when using Babel's automated instrumentation:

  1. The buried point module judges whether it has been imported and how to import it:
    1. In the execution of the Babel plug-in, ImportDeclarationanalyze whether the specified embedded module is included by traversing the code;
    2. Buried module import is realized through Babel built-in @babel/helper-module-importsmodule;
  2. How to generate and insert the buried point function into the source function;
    1. How to generate: template.statementGenerate the AST that calls the embedded function through the built-in API;
    2. How to insert: The types in the AST corresponding to different forms of functions include ClassMethod, ArrowFunctionExpression, , FunctionExpression, FunctionDeclarationand when Babel traverses them, insert the generated AST into the body of the corresponding node. When a function without a function body needs to be added and processed return value;

18. Tell me about JSON Web Token?

  1. Working principle:
    After server authentication, JWT generates a JSON object containing user information, time, security information, etc. to uniquely represent the current user status, and continues to carry it in subsequent data interactions to indicate the validity of the request.

  2. Data structure:
    JWT is a string with header, payload and signature connected by ".", and there is no line break in the JWT string .

  3. header is a JSON object used to describe some metadata;

  4. The format requirements of the payload are the same as those of the header, and the content mainly includes official defined fields + custom fields to meet the needs of business scenarios;

  5. Neither "Header" nor "Payload" mentions encryption, they are just encoding of characters, so we should not place some user-related security-related information in "Header" and "Payload", which does not prevent the above two blocks The content of is intercepted and tampered by the middleman, so "Signature" is needed;

signature = HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)
  1. Usage:
    The standard usage method is to add a set of information with the key as "Authorization" and the value as "Bearer" in the HTTP header. The specific storage of the token is handled according to the actual business.
    4. Precautions:

  2. JWT is not encrypted by default, but it can be encrypted by itself.

  3. If it is not encrypted by default, do not put confidential data into the JWT.

  4. HTTPS is recommended to prevent man-in-the-middle attacks.

19. What is the difference between toString() and join() in JavaScript?

// 声明两个不同的数组
const fruitList = ['苹果', '香蕉', '百香果']
const objList = [
  {
    
    
    name: '张三',
    age: 16
  },
  {
    
    
    name: '李斯',
    age: 18    
  }
]
// 通过toString()直接进行转换为字符串
console.log(fruitList.toString()) // '苹果,香蕉,百香果'
console.log(objList.toString()) // '[object Object],[object Object]'

// 通过join()自定义拼接进行转换为字符串
console.log(fruitList.join()) // '苹果,香蕉,百香果'
console.log(fruitList.join(',')) // '苹果,香蕉,百香果'
console.log(fruitList.join('、')) // '苹果、香蕉、百香果'
console.log(fruitList.join('分割')) // '苹果分割香蕉分割百香果'
console.log(objList.join()) // '[object Object],[object Object]'

Summary conclusion:
toString() and join() put all the elements in the array into a string.
When the internal parameters of the join() function are empty, join() is equivalent to toString().
When the internal parameter of the join(',') function is a comma character, it means that the array is separated by a comma, which is equivalent to the internal parameter being empty.
When the internal parameter of the join(',') function is a comma character, it means that the array is divided by a comma.
When the internal parameter of the join('split') function is a string, it means to use the 'split' string to split the array.

20. The difference between null / undefined

Null value : belongs to the null type, representing "null value", representing an empty object pointer; use typeof operation to get "object", so you can think of it as a special object value.
Undefined value : It belongs to the undefined type. When a declared variable is uninitialized and assigned, the result is undefined. Use typeof operation to get "undefined".

21. What is the difference between looping through map() and forEach()?

array.map(function(currentValue, index, arr), thisValue)
const nums = [4, 9, 16, 25]
const emptyList = []
const doubleNums = nums.map(Math.sqrt)

console.log(doubleNums) // [2, 3, 4, 5]
console.log(nums) // [4, 9, 16, 25]
console.log(emptyList.map(Math.sqrt)) // []

Definition and usage:
The map() method returns a new array, and the elements in the array are the values ​​processed by calling the function on the original array elements.
The map() method processes elements sequentially in the original array element order.
map() does not check for empty arrays.
map() does not mutate the original array.

array.forEach(function(currentValue, index, arr), thisValue)
const nums = [4, 9, 16, 25]
const emptyList = []
const doubleNums = nums.forEach(Math.sqrt)

console.log(doubleNums) // undefined
console.log(emptyList.forEach(Math.sqrt)) // undefined

Definition and Usage:
The forEach() method is used to call each element of the array and pass the element to the callback function.
forEach() will not execute the callback function for an empty array.
Difference:
the forEach() method will not return the execution result, but undefined. In other words, forEach() will modify the original array. The map() method will get a new array and return it.
map() will allocate memory space to store the new array and return, forEach() will not return data.
forEach() allows the callback to change the elements of the original array. map() returns a new array.

22. What is the difference between for/in and for/of?

Array.prototype.method = function () {
    
    }
let myArray = [1, 2, 3]
myArray.name = '数组';

for (let index in myArray) {
    
    
  console.log(index) // 0,1,2, name, method
  console.log(myArray[index]) //1,2,3,数组,f() {}
}

for (let val of myArray) {
    
    
  console.log(val) // 1,2,3
}

The most direct difference is: for/in traverses the index of the array, while for/of traverses the array element value .
Defects of for/in traversal:

  1. The index is a number of string type, so geometric operations cannot be performed directly
  2. The traversal order may not be the actual internal order
  3. for/in iterates over all enumerable properties of the array, including prototypes.

So it is generally used to traverse objects, not arrays.
Defects of for/of traversal:
for/of does not support ordinary objects. If you want to traverse the properties of an object, you can use the for/in loop, or the built-in Object.keys() method:
Object.keys(obj) to get the instance properties of the object An array of components, excluding prototype methods and properties

for(let key of Object.keys(obj)) {
    
    
  console.log(key + ":" + Object[key])
}

The for/of statement creates a loop to iterate over iterable objects, allowing iterative data structures such as Arrays, Strings, Map, and Set to be traversed

// variable 每个迭代的属性值被分配给该变量。
// iterable 一个具有可枚举属性并且可以迭代的对象。
for(let variable of iterable) {
    
    
  statement
}

In general: for/in traverses objects; for/of traverses arrays

23. What is the rendering layer composition of css, and how does the browser create a new rendering layer

Each node in the DOM tree corresponds to a rendering object (RenderObject). When their rendering objects are in the same coordinate space (z-axis space), a RenderLayers, that is, a rendering layer, will be formed. The rendering layer will ensure that the page elements are stacked in the correct order. At this time, layer composition (composite) will appear, so as to correctly handle the display of transparent elements and overlapping elements. This process is especially important for pages with overlapping elements, because once the layers are merged in the wrong order, the elements will display abnormally.

How browsers create new rendering layers

  • root element document
  • Have clear positioning attributes (relative, fixed, sticky, absolute)
  • opacity < 1
  • Has CSS filter property
  • Has CSS mask property
  • Has the CSS mix-blend-mode property and its value is not normal
  • Has the CSS transform property and its value is not none
  • The backface-visibility property is hidden
  • Has the CSS reflection property
  • Has the CSS column-count property and the value is not auto or has the CSS column-width property and the value is not auto
  • Currently there are animations applied to opacity, transform, fliter, backdrop-filter
  • overflow is not visible

24. The characteristics of routing principles history and hash routing methods

hash mode

  1. The value of location.hash is actually the thing after # in the URL. Its characteristic is that although the hash appears in the URL, it will not be included in the HTTP request and has no effect on the backend at all, so changing the hash will not reload the page.
  2. You can add listener events for hash changes

window.addEventListener(“hashchange”, funcRef, false);
Every time you change the hash (window.location.hash), a record will be added in the browser’s access history. Using the above characteristics of hash, you can realize the front-end routing “update” View but do not re-request the page"
feature: good compatibility but not beautiful

history mode

Take advantage of the new pushState() and replaceState() methods in the HTML5 History Interface.
These two methods are applied to the history record station of the browser. Based on the existing back, forward and go, they provide the function of modifying the history record. These two methods have a common feature: when they are called to modify the browser history stack, although the current URL has changed, the browser will not refresh the page, which is the front-end route of the single-page application "update the view but do not re-request page" provides the basis.
Features: Although it is beautiful, 404 will appear when refreshing, and the backend needs to be configured

25. What is the difference between XMLHttpRequest and fetch?

(1).XMLHttpRequest objects are supported in all modern browsers. Fetch is a new native JavaScript API that is currently supported by most browsers. (2)
.XMLHttpRequest executes callbacks based on onreadystatechange. Fetch API uses Promise to avoid callbacks .
(3). Fetch only reports errors for network requests, and treats 400 and 500 as successful requests, which need to be encapsulated for processing.
(4). The Fetch request does not have a cookie by default, and fetch(url, {credentials: 'include'}) needs to be set.
(5). Fetch does not support abort, because Fetch returns a promise and does not support timeout control. The timeout control implemented by using setTimeout and Promise.reject cannot prevent the request process from continuing to run in the background, resulting in a waste of quantity.
(6). In the .fetch() example, the URL endpoint defined by a string can be passed, or a configurable Request object can be passed.
(7). It is cumbersome to manage cache in XMLHttpRequest. The Fetch object has built-in support for cache:
(8). In cross-domain requests, Fetch provides a mode attribute, which can set the 'no-cors' attribute in the parameter.
(9). By default, both fetch() and XMLHttpRequest follow server redirection. However, fetch() provides optional options in the parameters:
redirect
'follow' - follow all redirects (default)
'error' - abort (reject) if a redirect occurs
'manual' - return a manually processed response

(10).XMLHttpRequest reads the entire response into a memory buffer, but fetch() can stream request and response data, which is a new technology that allows you to process smaller chunks of data when sending or receiving.
(11). Fetch is fully supported in Deno and Node, and XMLHttpRequest is only supported on the client side.

26. How does the front end implement large file downloads?

(1). Partial download can be used if the backend service supports it.
(2). Files on the cloud can be downloaded through the default mechanism of the browser using the a tag method.
(3). Realized with the help of StreamAPI and Service Worker

27. Several common front-end micro-services and their implementation principles

The micro-front-end architecture applies the concept of back-end micro-services to the browser, that is, transforms a web application from a single application to an application that aggregates multiple small front-end applications into one.
Micro-frontend architecture can generally be implemented in the following ways:

  1. route distribution

Distribute different services to different, independent front-end applications through routing. It can usually be implemented through the reverse proxy of the HTTP server, or the routing that comes with the application framework.

  1. via iframe container

Use iframe to create a new independent host environment to run independent front-end applications

  1. Front-end micro-service

Introduce or create DOM at the appropriate place on the page. When the user visits the corresponding URL, the corresponding application is loaded and the application can be uninstalled.

  1. App widgetization

It is also called combined integration, that is, through software engineering, the application is split and reassembled in steps such as pre-construction, construction, and post-construction.

  1. Based on Web Components

Use Web Components technology to build framework-independent components, and then introduce these components in the corresponding framework

28. What are the solutions for front-end deployment?

There are roughly three ways of front-end deployment,

  • Use Nginx, Tomcat, IIS and other web servers to deploy
  • Docker deployment
  • OSS+CDN deployment, or COS

29. There are several common publishing schemes

  1. blue-green release

Blue-green release refers to the one-click release method of updating the application by switching the gateway traffic after passing the release test of the new application during the release process.

  1. rolling release

Generally, one or more services are stopped, an update is performed, and they are put into use again, and the cycle repeats until all the public services in the microservice are updated to the new version.

  1. Gray release

It refers to a publishing method that can smoothly transition between black and white. AB test is a grayscale release method that allows some users to continue using A and some users to start using B. If users have no objection to B, then gradually expand the scope and migrate all users to B. Grayscale release can ensure the stability of the overall system. Problems can be found and adjusted during the initial grayscale to ensure their impact. What we usually call canary deployment is also a way of grayscale release.

30. How to design an A/B plan

A/B publishing is a relatively advanced traffic distribution scheme, such as requesting different versions of applications based on whether the URL matches, or distinguishing users based on a custom parameter under the Header, so that requests for different versions of applications involve traffic management strategies
, Istio, docker, k8s and other technologies
are gradually deepening the concept of micro-services and cloud native. The existing front-end development methods and front-end architecture will also continue to change. Making good use of the above technologies can achieve faster expansion and more stable delivery. The connection between applications will become closer, and the front end in the next few years will also be the era of microservices.

Conclusion:

       Seeing this, I wonder if you have gained anything? If you have more anti-freezing guides, you are welcome to leave them in the comment area and leave them to friends who need them. If you still have questions about the above content, please leave a message and exchange them. I hope that every Internet winter will not freeze any one. Be prepared JY~

Guess you like

Origin blog.csdn.net/gaojinbo0531/article/details/129404773