1. The simulation of new

1-1. Application Scenarios

When multiple objects need to be created, the loop “repeats” many variables, consuming memory. If new is used, then the repeated properties are on the “prototype” and do not consume memory.

1-2. Significance

Code saving, syntactic sugar, can have all the “properties and methods” in use constructors, and can be “extended”.

1-3. Implementation steps

  1. The parameters passed in are: constructor and function parameters
  2. Create an empty object
  3. Make an empty object’s __proto__ point to the constructor’s prototype.
  4. Bind this to the empty object and execute the constructor
  5. Determine the return value of the constructor and, if it is an object, return it directly. If not, it returns the object from which it was created

1-4. Code implementation

Text code (” Text code is the same as image code below, but image code highlighting is more powerful “) :

// Create a new constructor -- a function for new// Constructor is a special method used to assign initial values to object member variables when an object is createdfunction Dog(name){
// This refers to the window, so we need to redirect this to itself to mount the property successfully  this.name = name
 this.say = function() {  console.log("my name is" + this.name);  } }  // Write the new functionfunction_new(fn,... arg){ const obj = {}; // Mount the constructor prototype to the new object Object.setPrototypeOf(obj, fn.prototype) // Point this to the new object and execute the constructor let result = fn.apply(obj, arg);  return result instanceof Object ? result : obj } Copy the code
/ / verificationvar dog = _new(Dog, "caigou")
dog.say(); // my name is caigouCopy the code

Image code:


2. Instanceof simulation

2-1. Application Scenarios

Tests whether an object is an instance of a class. Often used to determine the type of a reference type. That is, whether the object’s hermit stereotype matches the constructor’s display stereotype

2 – (2) usage

Such as:

console.log(1 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false  
console.log([] instanceof Array);                    // true
console.log(function(){} instanceof Function);       // true
console.log({} instanceof Object); // true console.log(null instanceof Object); // false Copy the code

2-3. The advantages and disadvantages

  • Advantages: Can distinguish Array, Object, and Function, suitable for judging custom class instance objects
  • Disadvantages: Number, Boolean, String Basic data types cannot be determined

2-4. Implementation steps

  1. The arguments passed in are instance L on the left, and constructor R on the right
  2. Handles bounds, and returns false if you want to detect an object of primitive type
  3. Take the prototype of the passed parameters, respectively
  4. Check whether the left prototype is null, if null returns false; Return true if both archetypes are equal, otherwise continue with the left archetype.

2-5. Code implementation

“Text code” (text code is the same as the image code below, but image code highlighting is more powerful) :

// Write the instanceof functionfunction instance_of(L, R){
// Verify that if it is a basic data type, return it directlyfalseBecause Instanceof can only determine the type of reference  const baseType = ['string'.'number'.'boolean'.'undefined'.'symbol']
  if(baseType.includes(typeof(L)) || L === null) { return false }
  let Lp = L.__proto__;  letRp = r.protoType // the function has the prototype property while(true) { if(Lp === null){// The top layer is not found, indicating a mismatch return false  }  if(Lp === Rp){  return true  }  Lp = Lp.__proto__  } } Copy the code
/ / testvar a = instance_of([],Array)
console.log(a) //true
Copy the code

Image code:


3. The simulation of the call

3-1. Application Scenarios

Change the direction of this. In general, in ES5 this always refers to the last method to call it; In es6 arrow function this refers to the non-arrow function at the nearest layer of the arrow function. So as we can see, this is often confusing, so JS implements a new function to help us avoid this confusion. Using call,apply, and bind(all three are roughly the same), this points to the object passed in. When the object does not exist:

  • Strict mode: This refers to undefined
  • In non-strict mode: This refers to window

3-2. Implementation steps

  1. The arguments passed in are: “The object to which this refers”, and the arguments to be passed in for “calling the function”
  2. Processing boundaries:
  • Object does not exist, this refers to window;
  • Call not a function, throw an error
  1. Mount “Call function” to the FN property of “object to which this points”.
  2. Execute the fn function on “the object to which this points”, pass in the argument, delete the FN attribute, and return the result.

3-3. Code implementation

“Text code” (text code is the same as the image code below, but image code highlighting is more powerful) :

// Write the call function// Call is on the function prototype, so we need to mount it here as wellFunction.prototype.call2 = function(obj, ... ary) {obj = obj || window; // if obj is empty, it points to windowobj.fn = this; // This refers to the function being called and mounts the function to the fn property of the current object if(typeof this ! ="function") { // boundary processing throw new TypeError("Erorr");  } /** The structure of the object to which this points obj:{  fn:bar() {} } * /// This refers to the object (obj) from which the last function (fn) was calledvar result = obj.fn(... ary); // This refers to the last object to call the function, so it points to obj// Delete after execution because the object does not have this fn property delete obj.fn;  return result; };  Copy the code
/ / testvar value = 2;
var obj1 = {
  value:1
}
function bar(name, age){  var myObj = {  name:name,  age:age,  value:this.value  }  console.log(this.value,myObj) } Bar. call2(null) // Print 2 {name: undefined, age: undefined, value: 2}bar.call2(obj1,"zi"."shu")// Print 1 {name:"zi", age: "shu", value: 1} Copy the code

Image code:


4. Simulate deep copy

4-1. Application Scenarios

When we need to use an object and modify its value without changing the original object, for example:

  • When a vUE child component receives the props value from the parent component and needs to modify the props value, an error is reported if the child component changes the props value. In this case, we can copy the props values in the data and then modify the corresponding values in the data.

4-2. Comparison of various methods

  1. JSON.parse(JSON.stringify(copyObj))

    advantagesUsing a simple

    disadvantages
  • If the function in the object, re, date, cannot be copied
  • Unable to copy properties and methods on the copyObj object prototype chain
  • When the data level is very deep, stack overflow occurs
  1. Handwritten copies

    advantagesYou can take into account all sorts of things

    disadvantagesImplementation is complicated

4-3. Differences between assignment, shallow copy and deep copy


4-4. Implementation steps

  1. If the passed object does not exist, null is returned; If it’s a special object, new a special object.
  2. Create an object, objClone, to hold the cloned objects.
  3. It then iterates through the object and, if it’s basic data, puts it directly into objClone
  4. If it’s an object, recurse.

4-5. Code implementation

“Text code” (text code is the same as the image code below, but image code highlighting is more powerful) :

// Write deep copy functionfunction deepClone(obj){
  if(obj == null){
    return null
  }
 if(obj instanceof RegExp){  return new RegExp(obj)  }  if(obj instanceof Date){  return new Date(obj)  }  var objClone = Array.isArray(obj) ? [] : {}  for(let key in obj){  if(obj.hasOwnProperty(key)){ // If it is still an object, recurse if(obj[key] && typeof obj[key] === "object") { objClone[key] = deepClone(obj[key])  }else{  objClone[key] = obj[key]  }  }  }  return objClone } Copy the code
/ / testvar dog = {
  name: {
    chineseName:"Dog"
  }
} var newDog = deepClone(dog) newDog.name.chineseName = "New dog" console.log("newDog",newDog)//{ name: { chineseName:"New dog"}} console.log("dog",dog)//{ name: { chineseName:"Dog"}} Copy the code

Image code:


5. Handwritten anti-shake function

5-1. Application Scenarios

In our normal development process, there are many scenarios that “trigger events frequently”, such as search box real-time request, onMousemove, Resize, onScroll and so on. For performance purposes, there are times when we can’t or don’t want to fire events too often, and function stabilization is to perform the callback after the event has been fired for n seconds, and “reset the timer” if it has been fired for “n seconds”.

5-2. Implementation steps

  1. The passed argument is the execution function fn, and the delay time wait.
  2. Define a timer variable n with an initial value of null.
  3. Returns a function that, when n is not null, means a timer has been created and should be cleared.
  4. Otherwise, reset the timer.

5-3. Code implementation

“Text code” (text code is the same as the image code below, but image code highlighting is more powerful) :

// Handwriting functionfunction debounce(fn, wait) {  var timer = null;
  return function() {
// If the timer is triggered within the specified time, it will clear the previous timer and reset the timer if(timer ! == null){ clearTimeout(timer)  } // reset the timer timer = setTimeout(fn, (wait));  } } Copy the code
/ / testfunction handle() {  console.log(Math.random())
}
// If the window size changes, handle is triggeredwindow.addEventListener("resize",debounce(handle,1000)) Copy the code

Image code:


How do you remember the anti-shake and throttling?

  • Chattering is chattering (” chattering delay “) : Chattering will delay execution
  • Throttling is “first-class” : the throttling time, only perform once

6. Handwritten throttle function

6-1. Application Scenarios

When an event is triggered, ensure that the function is called “once in a certain period of time”. For example, send requests every once in a while while the page is scrolling

6-2. Implementation steps

  1. The argument passed is to execute the function fn and wait time wait.
  2. Save the initial time now.
  3. Returns a function that updates now to the current time if the wait time is exceeded.

6-3. Code implementation

“Text code” (text code is the same as the image code below, but image code highlighting is more powerful) :

// Handwritten throttling functionfunction throttle(fn, wait. args){  var pre = Date.now();
  return function() {
// The function may have input parameters var context = this  var now = Date.now()  if(now - pre >= wait) {// Will execute the function this to the current scope fn.apply(context,args)  pre = Date.now()  }  } } Copy the code
/ / testvar name = "Summer"
function handle(val){
  console.log(val+this.name)
}
// Roll the mouse to trigger the handlewindow.addEventListener("scroll", throttle(handle,1000,"Dragon")) Copy the code

Image code:


7. Handwritten array deduplication

7-1. The new Set method

letArr =,2,2,2,33,33,4 [1]The console. The log (new Set (arr) [...]) / /,2,33,4 [1]Copy the code

7-2. Hand-write deduplication function (iterate to get unique value into new array)

letArr =,2,2,2,33,33,4 [1]let arrNew = []
arr.forEach((item,index)=>{
  if(arrNew.indexOf(item)===-1){
/ / orif(! arrNew.includes(item)){ arrNew.push(item)  } }) The console. The log (arrNew) / /,2,33,4 [1]Copy the code

7-3. Keys using map cannot be repeated

// Map keys cannot be duplicated, remove items with the same attributesfunction uniqBy(arr,key){
  return [...new Map(arr.map(item=>[item[key],item])).values()]
}
const singers = [
 {id:1,name:"lo"},  {id:1,name:"ming"},  {id:2,name:"li"} ] console.log(uniqBy(singers,"id"))// [{id:1,name:"ming"},{id:2,name:"li"}] Copy the code

Image code:


8. Array merge

8-1.concat

let arr = ["a"."b"]
let arr1 = ["c"."d"]
console.log(arr.concat(arr1))//["a"."b"."c"."d"]
Copy the code

8-2. Es6 display operator

let arr2 = [...arr,...arr1]
console.log(arr2)//["a"."b"."c"."d"]
Copy the code

Image code:


9. Array expansion

9-1. flat

letArr = [1, 2, 3, 4], [5, 6, 7,8,9] []]console.log(arr.flat(Infinity))//[1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy the code

9-2. join, split

console.log(arr.toString().split(",").map(Number))//[1, 2, 3, 4, 5, 6, 7, 8, 9] 
console.log(arr.join().split(",").map(Number))//[1, 2, 3, 4, 5, 6, 7, 8, 9] 
Copy the code

Image code:


10. Check whether it is an array

Let arr = [1, 2]

10-1. instanceof

console.log(arr instanceof Array)
Copy the code

10-2. constructor

console.log(arr.constructor === Array)
Copy the code

10-3. constructor

console.log(arr.constructor === Array)
Copy the code

10-4. Methods such as push to determine whether an object has an array

console.log(!! arr.push && !! arr.concat)Copy the code

10-5. constructor

console.log(Array.isArray(arr))
Copy the code

11. The sorting

(1) Bubble sort

concept

Starting with the first element, compare the current element to the next index element. If the current element is large, switch places and repeat until the last element is compared

Dynamic graph demonstration
Bubble sort
steps
  1. So let’s go over how many numbers we have and compare them to the others
  2. How many times do I have to compare each number to the others
  3. If the former number is less than the latter, it switches places
Handwritten code
function bubbleSort(arr) {
    var len = arr.length;
// How many numbers to compare with other numbers    for (var i = 0; i < len; i++) {
// How many times should each number be compared to the others for (var j = 0; j < len - 1 - i; j++) {  if(arr[j] > ARr [j+1]) {// Compare adjacent elements in pairs// Element swap [arr[j+1],arr[j]] = [arr[j],arr[j+1]];  }  }  }  return arr; } Copy the code
/ / testletArr =,44,6,77,3,7,99,12 [1]console.log(bubbleSort(arr))// [1, 3, 6, 7, 12, 44, 77, 99]
Copy the code

(2) Quicksort

concept

Within the data set, find a reference point, create two arrays, one on the left and one on the right, and use recursion for the next comparison.

Dynamic graph demonstration

steps
  1. So let’s do the boundary treatment
  2. Define the left and right array variables
  3. Take the middle of the array, find the middle value through this position, and delete it from the original array
  4. Iterate through the array, determine the size of the current item, and place it on the corresponding side
  5. After traversing, recurse the left and right arrays and concatenate the middle numbers.
Handwritten code
  function quickSort(arr) {
      if(! Array.isArray(arr))return;
      if (arr.length <= 1) return arr;
      var left = [], right = [];
// Use the middle position as the subscript var num = Math.floor(arr.length / 2); // arr.splice(num,1); // arr.splice(num,1); var numValue = arr.splice(num, 1)[0];  for (var i = 0; i < arr.length; i++) {  if (arr[i] > numValue) {  right.push(arr[i]);  } else {  left.push(arr[i]);  }  }  return [...quickSort(left), numValue, ...quickSort(right)]  } Copy the code
/ / testletArr =,44,6,77,3,7,99,12 [1]console.log(quickSort(arr))// [1, 3, 6, 7, 12, 44, 77, 99]
Copy the code

Inherited 12.

(1) Prototype chain inheritance

Introduction to the

Core:

  • Using an “instance” of a parent class as a “prototype” of a subclass

Advantages:

  • The implementation is simple and easy to understand

Disadvantages:

  • Stereotype attributes that contain reference type values are shared by all instances, causing changes to one instance to “affect” the other.
  • To add attributes and methods to a subclass, it must be executed after a statement such as new Cat(), not in a constructor. For example, when creating an instance of Child, no arguments are passed to Cat. Because of these two problems, prototype chains alone are rarely used in practice.
Handwritten code
/ / parent classfunction Cat () {
    this.name = 'orange cat';
}
Cat.prototype.getName = function () {
 console.log(this.name); } / / subclassfunction Child () {} // Use an instance of the parent class as a prototype for the subclassChild.prototype = new Cat(); Copy the code
/ / testvar child1 = new Child(); // We need to get the getName from the object property (obj.fn), so we need to new an objectThe console. The log (child1 getName ()) / / orange catCopy the code
To reassure
  • Some may wonder why we define a Child function:

    • Because inheritance is a subclass inheriting from its parent, our parent is the Cat constructor. So we’re missing a subclass, so we’re going to create a subclass, and notice: when we say parent class, subclass means constructor
  • Why new Child() when we already have the Child constructor:

    • In fact, this step is to test whether the subclass has a parent class method. The Child itself is just a constructor, and we need to get an instance of it and see if it has a method on it to see if the Child completes inheritance.

(2) Borrow constructor inheritance

Introduction to the

Core:

  • By introducing a “superclass constructor” into a subclass function with.call() and.apply(), you “copy” the instance properties of the superclass to the subclass, “without using the stereotype.”

Advantages:

    1. Only the properties of the superclass constructor are inherited, not the properties of the superclass prototype
    1. Two disadvantages of prototype chain inheritance are solved
    1. You can inherit multiple constructor properties (call multiple).
    1. Arguments can be passed to the parent in a child instance

Disadvantages:

    1. Only attributes of the parent constructor can be inherited.
    1. Constructor reuse cannot be implemented. (Call it again every time you use it)
    1. Each new instance has a bloated copy of the superclass constructor. So this technique is rarely used alone.
Handwritten code
/ / parent classfunction SuperType(name){
      this.name=name;
}
/ / subclassfunction Child(name,age){ // Introduce the superclass constructor SuperType into Child by referring to this in SuperType to Child//Child inherits SuperType and also passes arguments SuperType.call(this,name); // Instance properties this.age=age; } Copy the code
/ / testvar Child1=new Child("mary", 22);console.log(Child1.name);  //mary
console.log(Child1.age); / / 22console.log(Child1 instanceof SuperType);  //false
Copy the code
To reassure
  • Advantage 1:

    • Since the inheritance uses “call”, which is equivalent to replacing “this” with “Child” in the original SuperType function, the Child also has a name attribute. Note: “We didn’t use the prototype at all.”
  • Advantage 2:

    • Properties are not shared by all instances because “no stereotype is used”; You can add new attributes and arguments to the constructor: for example, supertype.call (this,name), which passes a “name” value to the parent class (the attribute value is “dynamic”). In prototype inheritance, the parent class can only be “written dead” : this.name = ‘orange cat’. In addition, this.age=age in Child also adds an “attribute” directly to the constructor.

(3) Combination inheritance

Introduction to the

Core:

  • The combination of prototype chain inheritance and construction inheritance combines the advantages of the two modes, “parameter transfer” and “reuse”.
  • Idea is:
    • Inheritance of instance properties by borrowing constructors
    • Inheritance of the Prototype Method using the Prototype Chain
    • In this way, functions can be reused by defining methods on prototypes, while ensuring that each instance has its own attributes.
  • Is the most commonly used inheritance pattern in JavaScript.

Advantages:

    1. Can inherit the attributes of the parent class prototype, can pass parameters, reusable.
    1. The constructor properties introduced by each new instance are private.

Disadvantages:

    1. The parent constructor is called twice (call once, new once), and the subclass’s constructor replaces the prototype’s parent constructor.
Handwritten code
/ / parent classfunction SuperType(name){
      this.name=name;
      this.colors=["red"."blue"."green"];
}
SuperType.prototype.sayName=function() { console.log(this.name); }; / / subclassfunction Child(name, age){ // attribute SuperType.call(this,name);  this.age=age; } // Use the following methodChild.prototype=new SuperType(); Child.prototype.constructor=Child; Copy the code
/ / testChild.prototype.sayAge=function() {      console.log(this.age);
};
var Child1=new Child("mary", 22);
Child1.colors.push("black"); console.log(Child1.colors); //red,blue,green,black Child1.sayName(); //mary Child1.sayAge(); / / 22Copy the code

(4) Original type inheritance

Introduction to the

Core:

  • Create is a mock implementation of ES5 Object.create that uses the “passed Object” as a prototype for the “created Object”.
  • It’s like copying an object and wrapping it with a function.

“Advantages:” Reference prototype chain inheritance

“Disadvantages:” Reference to prototype chain inheritance

Handwritten code
function createObj(o) {
    function F() {}    F.prototype = o;
    return new F();
}
Copy the code
/ / testvar person = {
    name: 'kevin'.    friends: ['daisy'.'kelly']
}
 var person1 = createObj(person); var person2 = createObj(person);  person1.name = 'person1'; console.log(person2.name); // kevin  person1.firends.push('taylor'); console.log(person2.friends); / / /"daisy"."kelly"."taylor"]  Copy the code

Note: Person1. name = ‘person1’; person2.name = ‘person1’; person1.name = ‘person1’; You did not change the name value on the stereotype.

(5) Parasitic inheritance

Introduction to the

Core:

  • It’s just a case of the original inheritance.
  • Create a function that encapsulates only the inheritance process, internally does the enhancement object in some form, and finally returns the object.

Advantages:

  • Instead of creating a custom type, this function automatically becomes the new object being created because it just returns the object (this one) around the shell.

Disadvantages:

  • Like borrowing the constructor pattern, methods are created each time an object is created.
  • No prototype, no reuse.
Handwritten code
// There is a function outside the original formfunction createObj (o) {
// This step is shorthand for primitive inheritance    var clone = object.create(o);
// Add attributes clone.sayName = function () {  console.log('hi');  }  return clone; }  Copy the code

(6) Parasitic combinatorial inheritance

Introduction to the

“Core:” is actually a combination of three inheritance modes: parasitic, prototype-chain inheritance, and constructional inheritance

  • Parasitism: returns an object within a function and then calls
  • Combination:
    • 1. The prototype of a function is equal to another instance.
    • 2. Use apply or call to introduce another constructor that takes arguments

Advantages:

  • Fixed an issue with combination inheritance

Disadvantages:

  • Like borrowing the constructor pattern, methods are created each time an object is created.
  • No prototype, no reuse.
Handwritten code
/ / parent classfunction Parent (name) {
    this.name = name;
    this.colors = ['red'.'blue'.'green'];
}
Parent.prototype.getName = function () {  console.log(this.name) } / / subclassfunction Child (name, age) { // Construct inheritance Parent.call(this, name);  this.age = age; }  // Three key steps// set a layer of functions, parasitic inheritancevar F = function () {};  F.prototype = Parent.prototype; // Prototype chain inheritanceChild.prototype = new F();   var child1 = new Child('kevin'.'18');  console.log(child1); Copy the code

This article is formatted using MDNICE