Image stabilization function

Cancels the previous delayed call method each time the event is emitted

* @param (fn, wait) fn- function, */ function debounce(fn, wait = 500) {let timer = null return function(... args) { if(timer) { clearTimeout(timer) } timer = setTimeout(() => { fn.apply(this, args) timer = null }, wait) } }Copy the code
  • use
<input type="input" id="username" /> // JS const inputEL = document.querySelector('#username') const listenFn = debounce(function(event) { console.log(event.target.value) }, 200) inputEL.addEventListener('input', listenFn)Copy the code

Throttling function

Whatever happens, it must happen once in a while, right

* @param (fn, wait) fn- function, */ function throttle(fn, wait = 500) {let timer = null return function(... Args) {// The last timer task has not been executed, If (timer) {return} timer = setTimeout(() => {fn. Apply (this, args) timer = null}, wait)}}Copy the code
  • use
  function sayHi(e) {
    console.log(e.target.innerWidth, e.target.innerHeight)
  }
  window.addEventListener('resize', throttle(sayHi, 2000))
Copy the code

Fibonacci numbers

The title comes from

The Rikon-Fibonacci series

Description:

  • Write a function, input n, to find the NTH term of the Fibonacci sequence. The Fibonacci sequence is defined as follows:
F (0) = 0, F (1) = 1, F (N) = F (N - 1) + F (N - 2), where N > 1.Copy the code

The Fibonacci sequence starts with 0 and 1, and the Fibonacci numbers that follow are the sum of the previous two numbers. If the result is greater than 1000000007, you need to take the module. If the initial result is 1000000008, return 1.

Method 1: recursion + closure

/** * @description uses recursion + closure * @param {number} n * @return {number} */ const fib = function (n) {// cache, Const cache = new Map([[0, 0], [1, 1], [2, 1],]) If (cache.has(n)) {return cache.get(n)} // f(n) = f(n-2) + f(n-1) let result = inner(n-2) + inner(n-1) // Results over 1000000007, If (result > 1000000007) {result = result % 1000000007} result) return result } return inner(n) }Copy the code

Mode 2: Pure traversal (dynamic programming)

/** * @param {number} n * @return {number} */ const fib = function(n) {// Const map = new map ([[0, 0], [1, 1], [2, 1), ]) if(n <= 2) { return map.get(n) } let i = 3 let first = map.get(1) let second = map.get(2) while(i <= n) { let result = second + first if(result > 1000000007) {result = result % 1000000007} First = second second = result i++} return second}Copy the code

Handwritten call function

  • Principle: When a function is called as an object property, this refers to the object

  • Thoughts and ideas:

  • To obtainthisArgParameter and residual parameter
  • Access to callcallSet the function tothisArg.funcOn the properties
  • ThisArg. Func function is executed and the result is received
  • Remove thisArg func function
  • Return execution result
Function.prototype.myCall = function(thisArg, ... ThisArg = thisArg == null? window : ThisArg. Func = thisArg. Func; thisArg. Func = this; Const result = thisarg.func (... ThisArg. Func delete thisArg. FuncCopy the code
  • Test myCall
function sayHello(time) { console.log(`${this.name} say ${this.word} at ${time}`); } const bottle = { name: 'violet-mio', word: 'hello'} // myCall changes the this pointer in sayHello to the bottle object, MyCall (bottle, new Date().tolocaletimeString ())) // Violet -mio say hello at 4:46:28 PMCopy the code

Handwritten bind

  • To obtainthisArgandRemaining parameter args
  • Get the function that calls myBind, save tofunc
  • Create a new return functionresultFnIn resultFn, do the following logic
    • Obtain the secondArgs when resultFn is executed, and merge args and secondArgs
    • Determine whether to use the new keyword to execute the resultFn function
      • If so, the this inside the resultFn function remains the same
      • Otherwise, change this inside the resultFn function tothisArg
    • Execute through ApplyFunction funcAnd returns the execution result
  • Modify the prototype of the resultFn function to bind toObject.create(func.prototype)
Function.prototype.myBind = function(thisArg, ... args) { thisArg = thisArg == null ? // keep calling myBind const func = this const resultFn = function(... SecondArgs) {const fullArgs = args. Concat (secondArgs) const fullArgs = args. Const realThis = this instanceof resultFn? this : thisArg return func.apply(realThis, Prototype = object.create (func.prototype) return resultFn}Copy the code
  • Test myBind
Function Person(name, age) {console.log(' function call ') The __proto__ attribute of the instance object points to the constructor's Prototype console.log(' Use new', this.__proto__ === Person.prototype) this.name = name this.age = age } Person.prototype.sayHi = function() { Console. log('sayHi function execution '); console.log(this.name, this.age); } const obj = {name: 'I am the name of obj ', age: } const Student = person.bind (obj, 'name') // create Point with new, Const stu = new Student(' age') stu.sayHi() Const teaher = person.bind (obj, 'name') teaher()Copy the code

Write the Curry function

  • Get the original functionfnIs the length of an acceptable parameter
  • Define an array to cache the parameters in the recursive process
  • Returns the keratology function to collect arguments
  • In the Currization function
    • Merge the current parameter with the previous parameter
    • Determines whether an argument is greater than or equal to the length of an acceptable argument
      • If true, execute the original function
      • Otherwise, return the keratology function and continue the collection of parameters
Const curry = function (fn) {const limitLen = fn.length; Let params = [] return function _innerCurry(... Args) {// Merge parameters params = params.concat(args) // If the number of merged parameters is greater than or equal to the number of parameters accepted by fn if(params.length >= limitLen) {// Return the fn function Fn. apply(null, params)} else {// Return a currie function to collect the parameters return _innerCurry}}Copy the code
  • Do not use coriolissum(2)(3)(5)The calculation results of
function add(num1, num2, num3) {
  return num1 + num2 + num3
}

const sum = function(a) {
  return function(b) {
    return function(c) {
      return add(a, b, c)
    }
  }
}
console.log(sum(2)(3)(5))
Copy the code
  • Use the function keratology
const curriedAdd = curry(add)
console.log(curriedAdd(2)(3)(5))
Copy the code

Implement the new operator

  • Create an empty object that links the stereotype to the explicit stereotype of the constructor
  • Execute the constructor to change this to an empty object and save the result
  • The constructor returns the result if the object executes it; Otherwise return the obj object
function myNew(fn, ... Const obj = object.create (fn.prototype) const obj = object.create (fn.prototype); Const result = fn.apply(obj, args) const result = fn.apply(obj, args) const result = fn.apply(obj, args) Otherwise, return obj Object return result instanceof Object? result : obj }Copy the code

Es5 implements INHERITANCE from ES6 (parasitic composite inheritance)

  • To create aAn empty object.An empty objectThe prototype link toThe parent classtheExplicit prototypeon
  • An empty objecttheconstructorPoint to theA subclass
  • A subclassExplicit prototypePoint to theAn empty object
// function inherit(Child, Parent) {// create a 'empty object', Const obj = object.create (Parent. Prototype) // constructor 'points to' subclass 'obj.construct = Child Prototype = obj} function Person(name) {this.name = name this.colors = ['red', 'blue', 'green'] } Person.prototype.sayName = function () { console.log(this.name) } function Student(name, Age) {person. call(this, name) this.age = age} Person) // Subclass methods must set student.prototype. sayAge = function () {console.log(this.age)} const stu = new after inheritance Student('violet', 20) console.log(stu) stu.sayName() stu.sayAge()Copy the code

Write a promise

Implementation constructor

  • promiseThere are three statespending.fulfilled.rejected
  • promiseCan be caused bypendingChange forfulfilledorpendingChange forrejectedThe state is irreversible
  • createpromiseInstance, passing a functionexecutorFnDuring the instance, this function will be called immediately to call theresolveandrejectPass to the consumer
  • If business is normal, the consumer will callresolve()Function to pass in the success result
    • inresolve()Function to change the state tofulfilledAnd stores the successful value
  • If the business fails, the consumer callsreject()Function to pass in the cause of failure
    • inreject()Function to change the state torejectedAnd store the failure cause
Class MyPromise {// Promise has three states pending, depressing, rejected static PENDING = 'pending' static FULFILLED = 'fulfilled' static REJECTED = 'rejected' constructor(executorFn) Value = undefined // Success value this.reason = undefined // failure cause // Const resolve = (value) => {if(this.state === mypromise.pending) {// Change the state to progressively this.state == this // Call this method const reject = (reason) => {if(this.state === =) Mypromise.pending) {// Modify the state to REJECTED this.state = myPromise.rejected // This. Reason = Reason}} try {// Execute the executorFn function immediately, passing resove and reject to the user executorFn(resolve, reject)} Catch (error) { Reject (error)}}} const p = new MyPromise((resolve, Reject) = > {resolve (' resolved ') / / reject (' had rejected ')}). The console log (p)Copy the code

Implement then methods

When calling THEN, the Promise instance object is in a state of PENDING, depressing, and REJECTED

  • PENDING(wait state), the callback function needs to be collected before the state changes toFULFILLEDorREJECTED, executes the callback function
  • FULFILLED(Solved), you can directly execute the commandSuccessful callback function
  • FULFILLED(Solved), you can directly execute the commandFailed callback function
  • To support chained calls, the then method needs to return a new onePromise instance object
Constructor (executorFn) {// omit content... This.state = myPromise.pending // Initialize PENDING this.onResolvedCallbacks = [] // Store successful callbacks this.onRejectedCallbacks = [] Const resolve = (value) => {if(this.state === mypromise.pending) {// Remove onResolvedCallbacks function executed in sequence in the enclosing onResolvedCallbacks. ForEach (fn = > fn ())}} / / this method is called is const failure reject = (reason) = > { If (this. State = = = MyPromise. PENDING) {this. OnRejectedCallbacks. ForEach (fn = > fn ())}} / / omitted content... } /** * @description then function * @param takes two functions as arguments, This is a big pity, onFulfilled */ then(onFulfilled, Ondepressing === 'function'? // This is a big pity! // This is a big pity === 'function'? onFulfilled : (v) => v onRejected = typeof onRejected === 'function' ? onRejected : (err) => {throw err} const p1 = new MyPromise(resolve, reject) => { In performing the if (this. State = = = MyPromise. PENDING) {/ / cache the success callback this. OnResolvedCallbacks. Push ((() = > {setTimeout () = > {try { const newValue = onFulfilled(this.value) resolve(newValue) // p1.value = newValue } catch (err) { reject(err) } }) }) // Cache failed callback enclosing onRejectedCallbacks. Push ((() = > {setTimeout () = > {try {const newReason = onRejected (enclosing a tiny) Resolve (newReason) // p1.reason = newReason} Catch (err) {reject(err)}})})} // Resolve status if(this.state === This is a big pity) {// Use setTimeout to simulate asynchronous, SetTimeout (() => {try {// Retrieve the stored success value const newValue = ondepressing (this.value) resolve(newValue)} catch (err) {reject(err)}})} if(this.state === myPromise.rejected) {// Use setTimeout to simulate asyncio, SetTimeout (() => {try {// Fetch the stored success value const newReason = onRejected(this.reason) resolve(newReason)} catch (err) { reject(err) } }) } }) return p1 } }Copy the code

Optimize THEN: Extract common parts

Then internal code above, there are parts of the code similar, can sit down to extract

// then method, This is a big pity. Then (onFulfilled, onRejected) {return MyPromise((forget, onFulfilled)); reject) => { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (val) => val onRejected = typeof onRejected === 'function' ? onRejected : (err) => { throw err } const asyncHander = (cb, CurrentResult) => {setTimeout(() => {try {const newResult = cb(currentResult) // Passed to the next resolve(newResult)} catch (error) {reject(error)}})} // This is a big pity. State === MyPromise. asyncHander(onFulfilled, If (this.state === myPromise.rejected) {asyncHander(onRejected, This.reason)} // State is PENDING; Cache the callback function if (this. State = = = MyPromise. PENDING) {this. OnFulfilledCallbacks. Push (() = > {asyncHander (onFulfilled, this.value) }) this.onRejectedCallbacks.push(() => { asyncHander(onRejected, this.reason) }) } }) }Copy the code

Implementing catch methods

Catch is a shortened version of then, where onRejected is accepted and only onRejected is processed

  catch(onRejected) {
    return this.then(null, onRejected)
  }
Copy the code

Implement the resolve static method

Instantiate a Promise instance object and pass data to the Promise instance object. Resolve method

class MyPromise {
  static resolve(result) {
    return new MyPromise((resolve, reject) =>  {
      resolve(result)
    })
  }
}
Copy the code

Implement the reject static method

Instantiate a Promise instance object, passing the reason to the Promise instance object. Reject

class MyPromise {
  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason)
    })
  }
}
Copy the code

Implement the Race static method

  • Receives an array containing the Promise instance
  • Instantiate aNew Promise instance object
  • In the new Promise instance object, traverse the array of Promise instances
    • Takes an instance of a Promise and executes the promise instancethenMethod that returns as long as there is a complete state change (success or failure)
  • returnNew Promise instance object
Class MyPromise {// Return static race(promiseList) {return new MyPromise((resolve, resolve)) reject) => { promiseList.forEach(p => { p.then(resolve, reject) }) }) } }Copy the code

Implement all static methods

  • Receives an array containing the Promise instance

  • Instantiate a new Promise instance object

  • In the new Promise instance object, traverse the array of Promise instances

    • Takes an instance of a Promise and executes the promise instancethenMethod, which returns results on all successes and failed on one failure
  • Returns the new Promise instance object

Class MyPromise {// Execute array all promises, all successes return result, one failure, Static all(arr) {return new MyPromise((resolve, resolve, reject) => { const result = [] let index = 0 let length = arr.length arr.forEach(p => { p.then(res => { result.push(res) If (index++ === leng-1) {resolve(result)}}). Catch (err => {reject(err)})})}}Copy the code