Late night liver burst JS good article! In depth explanation of 2021 spring recruit interview questions

  • The topics selected in this paper are some classic and difficult JS interview questions
  • Gold content bar!, And will conduct in-depth explanation, professional explanation and analysis, including teaching and meeting

1. Deep copy and shallow copy

1.1 what is the difference between deep copy and shallow copy?

  • Deep copy and shallow copy are only for objects: complex objects (reference data types) such as object and array. There are no deep and shallow copies for basic data types, but only assignment operations.
  • In short, a shallow copy copies only the attributes of one layer of objects, while a deep copy recursively copies all levels.

for instance:

  • For example, when A and B break up, if they still have contact after breaking up, it is A shallow copy. If there is no contact after breaking up, they live their own lives and do not affect each other, it is called A deep copy.

1.2 is deconstruction a deep copy? Why?

  • Here is the interviewer digging a hole for you to examine your solid foundation.
  • Let's start with a set of codes:

Array deconstruction assignment

let arr2 = [1,2,3,4];
let newArr2 = [...arr2]; //Here is the deconstruction assignment
newArr2.push(5);
console.log(arr2, newArr2) // Results of arr2: 1,2,3,4 results of newarr2: 1,2,3,4,5

Object deconstruction assignment

let objA = {
 	name: 'Xiao Ming',
 	age: 8
}

let {name , age} = objA;
name = 'floret';
age = 10;
console.log(name, age, objA); // 1.name is floret, 2 Age is 10.3 Obja has not changed
  • According to the above, whether it is an array or an object, the new variables after deconstruction assignment have no influence on each other, so can we define: Deconstruction assignment is a deep copy?

  • Don't worry, let's look at a set of codes:

let arr3 = [[1,2],[3,4],[5,6]];
let newArr3 = [...arr3];
newArr3[0][1] = 33333;
console.log(newArr2, arr2)

The print result is:

  • We can see that the two sets of data affect each other
  • Then the question comes, why can the above code achieve mutual influence, but not below?
  • The answer is: deconstruction is not a real deep copy, but a pseudo deep copy
  • Conclusion: deconstruction can only deeply copy one-dimensional arrays and one-dimensional objects, and multi-dimensional arrays and objects are invalid

1.3 how to implement a deep copy?

There are two ways

  1. The relevant API code of JSON() is as follows:
let list = [
    {id: 1, stuName: 'Xiao Ming', class:'Class two of five years'},
    {id: 2, stuName: 'Xiao Hong', class:'Three classes in five years'},
    {id: 3, stuName: 'Little green', class:'Four classes in five years'}
]
// JSON.stringify: object to json string
// JSON.parse: converts json strings into json objects
let newList = JSON.parse(JSON.stringify(list));
let newObj = {
  id: 4,
  stuName: 'Xiaobai',
  class: 'Four classes in five years'
}   
newList.push(newObj)
newList[2].class = 'Every six years';
console.log(list, newList)

The printing results are as follows:

  • It can be seen that JSON related methods can indeed realize deep copy.
  • However, such methods can only be applied to some scenes
  • If there is a keyword such as function in the object, it will not work. The JSON() method will convert it into a string. Naturally, it will not work. The properties are different

2. Write a true deep copy with native JS, which is applicable to all scenarios:

  • The principle is simple and crude: take the values in the object one by one and redefine them
  • The code is as follows:
// Standard deep copy
function deepClone(source){
   // Determine whether the target of the copy is an array or an object
   const targetObj = source.constructor === Array ? [] : {}; 
   // Traversal target
   for(let keys in source){ 
     if(source.hasOwnProperty(keys)){
       // If the value is an object, recurse
       if(source[keys] && typeof source[keys] === 'object'){ 
         targetObj[keys] = source[keys].constructor === Array ? [] : {};
         targetObj[keys] = deepClone(source[keys]);
       }else{ 
         // If not, assign directly (basic type)
         targetObj[keys] = source[keys];
       }
     }
   }
   return targetObj;
 }
  • Test whether it works:
let objD = {
      name: 'Little pig',
      age: 20,
      detail: {
        color: 'white',
        type: 'Breeding pig'
      }
    }

    let newObjD = deepClone(objD);
    newObjD.detail.color = "black";
    console.log(objD, newObjD)
  • Actual results:
  • Experiments show that it really works
  • FAQ: it's really important to write down the deep copy code by hand

2. Prototype and prototype chain

1.1 what is the prototype? What's the usage?

  • prototype is one of the most important concepts in js. It is also a high-frequency question point in the interview, and it is also easy to cause confusion
  • Concept of prototype:
    • First, we make it clear that the prototype is an object
    • Each function has an attribute called prototype (function specific), which points to an object
    • Prototypes are the properties of function objects, not all objects. Objects are generated through the constructor new, so the constructor of the new object has an attribute called prototypes
    • When we define a function, the prototype properties of the function are defined and can be used. If it is not assigned a display value, its initial value is an empty Object object (added by default)
    • In short: prototypes are a unique property of functions
function fn1(a , b){
	return a*b;
}
console.log(fn1.prototype);  // Function added by default
console.log(fn1.constructor); // Constructor pointing

  • From the above, we can see that the prototype of function fn1 is Object (added by default, so it is empty)
  • The constructor of a Function is Function
  • Of course, we can also manually add prototype properties and methods to it:
 function fn1(a , b){
 	return a*b;
 }
// Manually add prototype properties and methods
// You can inherit through the new keyword
fn1.prototype.name = "Xiao Ming";
fn1.prototype.age = 18;
fn1.prototype.fn = function(){
    console.log("Age:"+this.age);
}

1.2 proto type chain

  • Definition: a finite chain between a finite instance object and a prototype is used to realize shared attributes and inheritance
  • From 1.1, we know that all functions are instances of Function. There is a prototype attribute prototype on the constructor, which is also an object; Then there is a constructor attribute on the prototype object, which points to the constructor;
  • There is one on the instance object_ proto _ Attribute, which also points to the prototype object, and this attribute is not a standard attribute and can not be used in programming. This attribute is used for internal use in the browser (only for viewing, not for operation)

You need to understand these words:

  • There is an attribute prototype in the function
  • Objects created by this function are connected to this property by default
  • _ proto_ It's from the perspective of objects
  • prototype is from the perspective of constructor
  • As shown below:

    Can't you understand the picture? Code to speak:
 function Person() {

 }
 Person.prototype.name = "Pig King";
 Person.prototype.age = 18;
 Person.prototype.getAge = function () {
     console.log(this.age);
 }

 let person1 = new  Person();
 console.log(person1);	
 console.log(person1.name);	// Inherit the properties of the parent	
 console.log(person1.constructor);   
  • Print results:

    Illustration:

  • person1 inherits Person() through the new keyword to get the properties and methods on the prototype chain

  • Generally speaking, Xiao Ming can't earn money when he goes to school. He can live in his parents' house and spend their money, which belongs to inheritance (blood inheritance).

  • The constructor within a function points to the function that constructs it

Search rules for prototype chain:

  • Search from bottom to top, layer by layer, until null is found. If NULL is not found, an error will be reported.
  1. Find its own attribute. If it is found, return the value
  2. If not, keep looking up (step by step)
  3. Until null is found
  4. If not found, throw an error

After watching it for so long, let's have a rest

3. this points to the problem

  • The direction of this cannot be determined when the function is created. Only when the function is executed can we determine who this is pointing to.
  • Generally speaking, who calls and points to (not all cases)
  • this in the outermost layer (pointing to window)
<script>
	console.log(this) // window
</script>
  • this in method (still pointing to window)
function a(){
  let userName = "Zhang San";
  console.log(this) // window
}
a();  // Equivalent to window a()
  • this in the object (depending on the call)
let o = {
   userName: 'Zhang San',
   fn:function(){
       console.log(this.userName);
   }
}
o.fn(); // Print result: Zhang San o calls this to point to o
  • The arrow function itself has no scope, so this points to its parent scope
var id = 66;
function fn5(){
    setTimeout(()=>{
        console.log(this.id + '====id')
    },500)
}
fn5({id:21});
  • Arrow function, this points to the object at the time of definition, fn5 under the scope of window, so this points to window;
  • The outer layer of the arrow function. this of the fn5 function is window
  • this of the arrow function has nothing to do with its execution. It is determined at the time of definition

4. What does the new keyword do?

function Person(){
     this.name = 'Zhu Xiaoming';
     this.fn = function(){
         console.log('The name is:' + this.name)
     }
 }

 let person1 = new Person();
  1. Create an empty object
  2. Link to prototype
  3. Bind this to point to and execute the constructor
  4. Make sure that the object is returned
  5. Code to explain:
let obj = new Object();
obj.__proto__= Person.prototype;  // Set prototype chain
 let result = Person.call(obj);  // Let this of Person point to obj and execute the body of Person function
 // Determine the return value type of Person:
 // If it is a value type, return obj. If it is a reference type, the object of this reference type is returned

 if (typeof(result) == "object"){
     person1 = result;
 }
 else{
     person1 = obj;;
 }
  • By default, the return value of the function is undefined, that is, if the defined return value is not displayed
  • Constructor is an exception. The new constructor returns the newly created object by default without return

5. How does native JS implement event delegation?

  • Event delegation is to use event bubbling and specify only one event handler to manage all events of a certain type
  • Take chestnuts for example:
    • Three colleagues are expected to receive the express on Monday. To sign for express delivery,
    • There are two ways: one is three people waiting for express delivery at the door of the company; Second, entrust the front desk MM to sign for it.
    • After receiving the express, the front desk MM will judge who the recipient is, and then sign for it according to the recipient's requirements,
    • Even pay for it. Another advantage of this scheme is that even if new employees (no matter how many) come to the company, the front desk MM will verify and sign for them after receiving the express sent to the new employees.

Specific implementation:

<!DOCTYPE html>
<html>
<head>
    <title>Event delegation</title>
</head>
<body>
    <ul id="ul">
        <li>0</li>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <button id="btn">Click me to add one li</button>
</body>
<script>
// Specific implementation of event delegation
let ul = document.getElementById("ul");
    ul.onclick = function (event) {
        event = event || window.event;
        let target = event.target;
        // Get target element
        if (target.nodeName == 'LI') {
            alert(target.innerHTML);
        }
    }
    // Bind click event for button
    let btn = document.getElementById('btn');
    btn.onclick = function () {
        let li = document.createElement('li');
        // The new li content is ul the number of current child elements
        li.textContent = ul.children.length;
        ul.appendChild(li);
    }
</script>
</html>

6. Write a bubble sort

  • Two for loops are done
  • Compare the size of two adjacent ones. If the latter is smaller than the former, exchange their positions, and so on
let array = [5, 4, 3, 2, 1];
let temp = 0;
for (var i = 0; i <array.length; i++){
	for (var j = 0; j <array.length - i; j++){
		if (array[j] > array[j + 1]){
			temp = array[j + 1];
			array[j + 1] = array[j];
			array[j] = temp;
		 }
}

8. How to implement array de duplication in one line of code?

[...new Set([1,2,3,1,'a',1,'a'])]

9. What is the difference between null and undefined?

  • null is an object representing "None". When converted to a value, it is 0 and the Boolean value is false
  • undefined is an original value indicating "None", which is NaN when converted to a numerical value
  • When the declared variable has not been initialized, the default value of the variable is undefined
  • null is used to indicate an object that does not yet exist. undefined means "missing value", that is, there should be a value here, but it has not been defined

1. I hope this article can be helpful to you. If there are any errors, please point them out

2. It's not easy to be original. Please use your little hands to make a fortune to support a wave (attention, comment, praise and collection)
3. Thank you. Good people will win a million tomorrow!

Added by shure2 on Tue, 01 Feb 2022 01:02:44 +0200