An overview of the

It has been less than half a year to prepare the algorithm, and I have also done some questions. Next, I will sort out the relevant knowledge points.

The front-end algorithm and back-end algorithm is no essential difference, but more and JS related handwriting problems. This issue will be on the common handwriting to do a sort, and JS weak association will not appear, such as to heavy or beat equality.

The data structure and algorithm sections will be updated later.

The source code of this part is here

apply

Calls a function with the specified this and the additional arguments as an array as the second argument

Function.prototype.apply(thisArg, argsArray)
Copy the code

In a concrete implementation, this could be used to get the current function (since apply is what the current function calls), mount it as a property, and then call thisArg.

/ / to this, here can't use arrow Function. The Function prototype. MyCall = Function (CTX,... args) { context = ctx ?? globalThis context.fn = this return context.fn(args) }Copy the code

call

It is basically the same as Apply, except that the other parameters take the form of a parameter list.

Function.prototype.call(thisArg, ... args)Copy the code

bind

Modify the function’s this, and you can preset some of the arguments as a list of arguments.

Function.prototype.bind(thisArg, ... args)Copy the code

Returns a new function that replaces this, so we use a closure to pre-store this and the preset parameters.

Function.prototype.myBind = function (ctx, ... args) { const context = ctx ?? globalThis return (... params)=> { this.apply(context, args.concat(params)) } }Copy the code

debounce

Tremble, that is, the event stops triggering a period of time after execution, if it is triggered again before reaching the cut-off event will be re-timed

Return a function that calls the new function where the old one was called.

function debounce(fn, timeout) { timer = null; return function (... args) { clearTimeout(timer); timer = setTimeout(fn, timeout, ... args); }; }Copy the code

throttle

Throttling refers to triggering only once at most in a period of time. The key to the implementation is to ignore the trigger for a period of time, which has two details, namely

  • Whether to execute when first triggered
  • If the last occurrence occurred in the corresponding period, do you want to delay the execution to the end of the period

There are two ways to do this

  • When implemented using timestamps, the second item above cannot be satisfied as long as the current time-initial time >time is executed
  • When timer triggering is used, the corresponding call is saved each time it is triggered and the execution is delayed until the end of the period. The first item above cannot be satisfied

Here you choose to improve on the second option, that is, execute the sequence immediately when the first call is made.

function throttle(fn, time) { let timer = null let isFirst = true return function (... args) { if(isFirst){ fn.apply(this,args) isFirst=false } if(timer===null){ timer= setTimeout(()=>{ timer=null fn.apply(this,args) },time) } } }Copy the code

new

This looks at what happens when we use the new call, i.e.

  1. Create an empty object obj
  2. Change obj’s __proto__ to the prototype of the corresponding constructor
  3. Execute the current constructor with obj for this and return res
  4. Return res if res is an object, obj otherwise
function CNew(ctr,... args) { const obj = {}; //1 Object.setPrototypeOf(obj, ctr.prototype); //2 const result = ctr.apply(obj, args); //3 return typeof result === "object" ? result : obj; / / 4}Copy the code

instanceof

Object instanceof constructor Determines whether the constructor’s prototype exists on the object’s prototype chain by looking for constructor along the object’s prototype chain until null is found

function myInstanceof(obj, constructor) { let cur = Object.getPrototypeOf(obj) while (cur) { if (cur === constructor.prototype) { return true } cur  = Object.getPrototypeOf(cur) } return false }Copy the code

eventEmitter

That is, to implement a publish and subscribe model, the implementation idea is

  • When initialized, a map is maintained in the eventEmitter instance where the key is the event name and the value is the array that holds the callbacks.
  • When subscribing, add or modify the callback array corresponding to the event name
  • When published, the callback array for the corresponding event is recursively called
  • Delete the corresponding key
  • When subscribing to once-used events, you can add the logic to remove the subscription in the callback

Specific reference source code

promise

To implement A promise, start by translating Promises/A+ into code.

Specific reference source code

deepclone

There are only seven basic types and one object type in JS, but when copying object types, the cloning methods of different instances can vary greatly, such as re types, date types, and even DOM nodes.

JSON.stringify

The most common use of deep cloning is JSON serialization and then parsing recovery, but with the following limitations.

Possible error

  • A circular reference
  • Does not support bigint

Process in serialization

  • If there is a toJSON() method, it will be used for serialization
  • Boolean, Number, and String are converted to the corresponding primitive type
  • Undefined, Functions, and Symbol are null, otherwise ignored
  • Date objects implement the toJSON() method and are treated as strings
  • Infinity and NaN and null themselves are treated as null
  • Other objects serialize only enumerable properties, such as Map key-value pairs that are not enumerable.

Manual implementation

It is recommended to use Lodash.clonedeep in production.