This binding

  1. Show binding call, apply, bind
  • Call, apply implementation: make this function a property that is passed to this(context) and called through context.fn(), then delete context.fn
Function.prototype.myCall = function (context, ... args) {
  let context = context || window;
  context.fn = this;
  letresult = context.fn(... args);delete context.fn;
  return result;
};

Function.prototype.myApply = function (ctx, arr) {
  let ctx = ctx || window;
  ctx.fn = this;
  letres = ctx.fn(... arr);delete ctx.fn;
  return res;
};
Copy the code
  • Bind implementation: returns a new function that forces the bind to this and inherits the properties of the original function
Function.prototype.myBind = function (ctx, ... args1) {
  let self = this;
  function fn(. args2) {
    return self.call(this instanceof fn ? this: ctx, ... args1, ... args2); } fn.prototype =Object.create(self.prototype);
  return fn;
};
Copy the code
  1. The new binding
  • This, the constructor of the new call, points to the new object returned
  • The new process:
    • Create () creates a new Object that inherits the constructor’s properties
    • Displays the binding constructor’s this to the object
    • Returns the object returned by the constructor if the constructor returns an object, otherwise the newly created object is returned
function myNew(. args) {
  const constructor = args.shift();
  const obj = Object.create(constructor.prototype);
  const res = constructor.apply(obj, args);
  return typeof res === 'object' ? res : obj;
}

Copy the code
  1. Priority of various bindings

New Binding > Show Binding > Implicit binding

Deep clone & shallow clone

  • Shallow clone: Only the first-layer value type can be copied, but not the reference type
function shallowClone(target) {
  let cloneTarget = {};
  for (const key in target) {
    cloneTarget[key] = target[key];
  }
  return cloneTarget;
}
Copy the code
  • Deep clone: Copy multiple layers of objects recursively
function deepClone(target) {
  if (typeoftarget ! = ='object') return target;
  let cloneTarget = target instanceof Array ? [] : {};
  for (const key in target) {
    if(target.hasOwnProperty(key)) { cloneTarget[key] = deepClone(target[key]); }}return cloneTarget;
}
Copy the code
  • Deep clone update: Stores cloned objects using map, avoiding circular references
function deepClone(target, map = new Map(a)) {
  let obj = target instanceof Array ? [] : {};
  if (typeoftarget ! = ='object') return target;
  if (map.get(target)) {
    return map.get(target);
  }
  map.set(target, obj);
  for (let key in Object.keys(target)) {
    obj[key] = deepClone(target[key], map);
  }
  return obj;
}

Copy the code

Js inheritance

The best native inheritance scheme: parasitic combination inheritance

function Person(name) {
  this.name = name;
}
Person.prototype.sayHello = function () {
  console.log(`Hi my name is The ${this.name}. `);
};

function Student(name, grade) {
  // Inherit the Person instance attributes
  Person.call(this, name);
  this.grade = grade;
}

// Inherit the Person prototype method
Object.prototype.create = function (target) {
  function F() {}
  F.prototype = target.prototype;
  return new F();
};

Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

Student.prototype.sayGrade = function () {
  console.log(`my grade is The ${this.grade}. `);
};
Copy the code

ES6 Inheritance: Class inheritance

  • Extends extends the stereotype property of the parent class;
  • Call super() to override constructor, inheriting the parent instance properties;
  • A call to super.method() overrides a superclass method
class Person {
  constructor(name) {
    this.name = name;
  }
  sayHello() {
    console.log('hello'); }}class Student extends Person {
  constructor(name, age) {
  // Inherit the Person instance attributes
    super(name);
    this.age = age
  }
  sayBye() {
    console.log('bye');
  }
  // Override the Person prototype method
  sayHello() {
    super.sayHello();
    this.sayBye(); }}Copy the code

Type judgment

Js variable values are classified into primitive types and reference types

  • Primitive types: number, string, Boolean, undefined, null, symbol
  • Reference types: objects, including Array, Function, Date, etc

Methods for determining types

  1. Return ‘object’ for all reference types. Note that typeof null also returns ‘object’.

  2. Instanceof: checks whether an Object is an instanceof a class. This can be used to check the reference types Array, Function, null instanceof Object

  3. Object. The prototype. ToString. Call () : can be used to determine all the primitive types and reference types, null returns’ [Object null], undefined returns’ [Object undefined] ‘

Instanceof code implementation: recursive loop

function myInstanceOf(instance, Class) {
  if (typeofinstance ! = ='object') return false;
  if(! instance.__proto__)return false;
  if (instance.__proto__ === Class.prototype) return true;
  return myInstanceOf(instance.__proto__, Class);
}
Copy the code

The function currization & compose

  1. Corrification: The function argument is passed in multiple times

fn(a,b,c) === curry(fn)(a)(b)(c)

function curry(fn) {
  return function curried(. args1) {
    if (args1.length < fn.length) {
    // If the parameter is not enough, continue currization
      return function (. args2) {
        return curried.call(this. args1, ... args2); }; }return fn.call(this. args1); }; }Copy the code

Applications: Redux middleware, HOC

  1. Compose:

compose(fn1, fn2, fn3)(args) === fn1(fn2(fn3(args)))

Application: Redux middleware

Throttling stabilization

  1. Throttling:

Only one event callback is fired at regular intervals

// immediate Can be triggered immediately or later
function throttle(fn, wait, immediate) {
  let timer;
  return function (. args) {
    let ctx = this;
    if (immediate) {
      if(! timer) { fn.call(ctx, ... args); timer =setTimeout(() = > {
          timer = null; }, wait); }}else {
      if(! timer) { timer =setTimeout(() = >{ fn.call(ctx, ... args); timer =null; }, wait); }}}; }Copy the code
  1. Stabilization:

Only the last event callback is called within a period of multiple triggered events

Application: Input field multiple inputs only get the final input value

Function debounce(fn, wait, immediate) {let timer; return function (... args) { let ctx = this; clearTimeout(timer); if (immediate) { if (! timer) fn.call(ctx, ... args); timer = setTimeout(() => { timer = null; }, wait); } else { timer = setTimeout(() => { fn.call(ctx, ... args); }, wait); }}; }Copy the code