The most complete handwritten JS interview questions

1 compose

Compose function: compose compose function

Function fn1(x) {return x + 1; } function fn2(x) { return x + 2; } function fn3(x) { return x + 3; } function fn4(x) { return x + 4; } const a = compose(fn1, fn2, fn3, fn4); console.log(a(1)); / / 1 + 4 + 3 + 2 + 1 = 11Copy the code

The implementation code is as follows:

function compose(... fn) { if (! fn.length) return (v) => v; if (fn.length === 1) return fn[0]; return fn.reduce( (pre, cur) => (... args) => pre(cur(... args)) ); }Copy the code

2 setTimeout Simulation setInterval (with the version of the clear timer)

Setinterval may have some problems when it is used to implement periodic calls. Can it be solved by settimeout

The implementation code is as follows:

function mySettimeout(fn, t) {
  let timer = null;
  function interval() {
    fn();
    timer = setTimeout(interval, t);
  }
  interval();
  return {
    cancel:()=>{
      clearTimeout(timer)
    }
  }
}
// let a=mySettimeout(()=>{
//   console.log(111);
// },1000)
// let b=mySettimeout(() => {
//   console.log(222)
// }, 1000)
Copy the code

Extension: Can we implement setTimeout in reverse using setInterval emulation?

const mySetTimeout = (fn, time) => { const timer = setInterval(() => { clearInterval(timer); fn(); }, time); }; // mySetTimeout(()=>{ // console.log(1); / /}, 1000)Copy the code

Extended thinking: Why use setTimeout emulation to implement setInterval? What are the pitfalls of setInterval?

In fact, the interviewer asked a lot of small make up here will not expand

3 Publish and subscribe mode

Implement a publish/subscribe mode with the on emit once off method

The implementation code is as follows:

class EventEmitter { constructor() { this.events = {}; } // Implement subscription on(type, callBack) {if (! this.events[type]) { this.events[type] = [callBack]; } else { this.events[type].push(callBack); }} // Delete subscription off(type, callBack) {if (! this.events[type]) return; this.events[type] = this.events[type].filter((item) => { return item ! == callBack; }); Function fn() {callBack(); function fn() {callBack(); this.off(type, fn); } this.on(type, fn); } // Emit the event emit(type,... rest) { this.events[type] && this.events[type].forEach((fn) => fn.apply(this, rest)); // Const event = new EventEmitter(); // const handle = (... rest) => { // console.log(rest); / /}; // event.on("click", handle); // event.emit("click", 1, 2, 3, 4); // event.off("click", handle); // event.emit("click", 1, 2); // event.once("dbClick", () => { // console.log(123456); / /}); // event.emit("dbClick"); // event.emit("dbClick");Copy the code

4 Array deduplication

The implementation code is as follows:

function uniqueArr(arr) {
  return [...new Set(arr)];
}
Copy the code

5 Array flattening

Implement a method to turn a multidimensional array into a one-dimensional array

The most common version of recursion is as follows:

function flatter(arr) { if (! arr.length) return; return arr.reduce( (pre, cur) => Array.isArray(cur) ? [...pre, ...flatter(cur)] : [...pre, cur], [] ); } // console.log(flatter([1, 2, [1, [2, 3, [4, 5, [6]]]]]));Copy the code

Extended thinking: Can it be done iteratively?

The implementation code is as follows:

function flatter(arr) { if (! arr.length) return; while (arr.some((item) => Array.isArray(item))) { arr = [].concat(... arr); } return arr; } // console.log(flatter([1, 2, [1, [2, 3, [4, 5, [6]]]]]));Copy the code

Parasitic combination inheritance

Implement a JS inheritance method that you think is good

The implementation code is as follows:

function Parent(name) {
  this.name = name;
  this.say = () => {
    console.log(111);
  };
}
Parent.prototype.play = () => {
  console.log(222);
};
function Children(name) {
  Parent.call(this);
  this.name = name;
}
Children.prototype = Object.create(Parent.prototype);
Children.prototype.constructor = Children;
// let child = new Children("111");
// // console.log(child.name);
// // child.say();
// // child.play();
Copy the code

Implement the Promise scheduler with parallel limitations

JS implements an asynchronous Scheduler with concurrency limits, which ensures that up to two tasks can run simultaneously

addTask(1000,"1"); addTask(500,"2"); addTask(300,"3"); addTask(400,"4"); The output sequence is: 2, 3, 1, 4 At the beginning, when task 1 and task 2 are executed for 500ms, task 2 is completed and output 2; when task 3 is executed for 800ms, task 3 is completed and output 3; when task 4 is executed for 1000ms, task 1 is completed and output 1, there are only 4 tasks left. When task 4 is executed for 1200ms, task 4 is completed. The output of 4Copy the code

The implementation code is as follows:

class Scheduler { constructor(limit) { this.queue = []; this.maxCount = limit; this.runCounts = 0; } add(time, order) { const promiseCreator = () => { return new Promise((resolve, reject) => { setTimeout(() => { console.log(order); resolve(); }, time); }); }; this.queue.push(promiseCreator); } taskStart() { for (let i = 0; i < this.maxCount; i++) { this.request(); } } request() { if (! this.queue || ! this.queue.length || this.runCounts >= this.maxCount) { return; } this.runCounts++; this.queue .shift()() .then(() => { this.runCounts--; this.request(); }); } } const scheduler = new Scheduler(2); const addTask = (time, order) => { scheduler.add(time, order); }; addTask(1000, "1"); addTask(500, "2"); addTask(300, "3"); addTask(400, "4"); scheduler.taskStart();Copy the code

8 New operator

Implementation of the handwritten new operator

The implementation code is as follows:

function myNew(fn, ... args) { let obj = Object.create(fn.prototype); let res = fn.call(obj, ... args); if (res && (typeof res === "object" || typeof res === "function")) { return res; } return obj; // // function Person(name, age) {// // this.name = name; // // this.age = age; // // } // // Person.prototype.say = function() { // // console.log(this.age); / / / /}; // // let p1 = myNew(Person, "lihua", 18); // // console.log(p1.name); // // console.log(p1); // // p1.say();Copy the code

9 call apply bind

Write call Apply bind by hand

The implementation code is as follows:

Function.prototype.myCall = function (context, ... args) { if (! context || context === null) { context = window; } // create a unique key for the internal method name of the context we construct. context[fn] = this; // This refers to the function that calls call // Executes the function and returns the result equivalent to calling itself as a method of the passed context. args); }; / / the apply consistent principle Just the second parameter is introduced to the array of the Function. The prototype. MyApply = Function (context, args) {if (! context || context === null) { context = window; } // create a unique key for the internal method name of the context we construct. context[fn] = this; Return context[fn](... args); }; / / bind implementation is a little complex Because he considered the situation more Also involves the parameter (similar Function curry) Function. The prototype. MyBind = Function (context,... args) { if (! context || context === null) { context = window; } // create a unique key for the internal method name of the context we construct. context[fn] = this; let _this = this; // bind const result = function (... InnerArgs) {// If we use the new operator as a constructor, we do not bind this. The new operator calls this to the result instance, which in turn inherits from _this.__proto__ === result.prototype //this instanceof result =>true // this.__proto__.__proto__ === result.prototype.__proto__ === _this.prototype; //this instanceof _this =>true if (this instanceof _this === = true) {if (this instanceof _this === true) _this; this[fn](... [...args, ...innerArgs]); Bind: delete this[fn]; } else {// If it is called as a normal function then it is very simple to change this to refer to the passed context context[fn](... [...args, ...innerArgs]); delete context[fn]; }}; Create result.prototype = object.create (this.prototype); return result; }; // function Person(name, age) {// console.log(name); // console.log(age); // console.log(this); // constructor this points to the instance object //} // // constructor prototype method // person.prototype. say = function() {// console.log(123); // let obj = {// objName: 'I am the name of obj ', // objAge: // function normalFun(name, age) {// console.log(name); // console.log(age); // console.log(this); // The normal function this points to the first argument to bind, which in our example is obj // console.log(this.objname); // console.log(this.objage); // console.log(this.objage); // let bindFun = person.mybind (obj, 'I am the name of the parameter passed in ') // let a = new bindFun(' I am the age of the parameter passed in ') // a.say() //123 // test again as a normal function call // let bindFun = Normalfun. myBind(obj, 'I am the name passed in ') // bindFun(' I am the age passed in ')Copy the code

10 Deep copy (considering copying Symbol type)

Implementation of the handwritten new operator

The implementation code is as follows:

function isObject(val) { return typeof val === "object" && val ! == null; } function deepClone(obj, hash = new WeakMap()) { if (! isObject(obj)) return obj; if (hash.has(obj)) { return hash.get(obj); } let target = Array.isArray(obj) ? [] : {}; hash.set(obj, target); Reflect.ownKeys(obj).forEach((item) => { if (isObject(obj[item])) { target[item] = deepClone(obj[item], hash); } else { target[item] = obj[item]; }}); return target; } // var obj1 = { // a:1, // b:{a:2} // }; // var obj2 = deepClone(obj1); // console.log(obj1);Copy the code

11 instanceof

Description: Handwriting instanceof operator implementation

The implementation code is as follows:

function myInstanceof(left, right) { while (true) { if (left === null) { return false; } if (left.__proto__ === right.prototype) { return true; } left = left.__proto__; }}Copy the code

12 currie

Currying, also known as Partial Evaluation, is a technique that converts a function that takes multiple arguments into a function that takes a single argument (the first argument of the original function), and returns a new function that takes the remaining arguments and returns a result. The core idea is to split the multi-parameter function into a single-parameter (or partial) function, and then return to call the next single-parameter (or partial) function, and process the remaining parameters in turn.

The implementation code is as follows:

function currying(fn, ... args) { const length = fn.length; let allArgs = [...args]; const res = (... newArgs) => { allArgs = [...allArgs, ...newArgs]; if (allArgs.length === length) { return fn(... allArgs); } else { return res; }}; return res; } / / usage is as follows: / / const add = (a, b, c) = > a + b + c; // const a = currying(add, 1); / / the console log (a) (2, 3)Copy the code

Bubble sort – time complexity n^2

Implement a bubble sort

The implementation code is as follows:

Function bubbleSort(arr) {const len = arr.length; For (let I = 0; for (let I = 0; i < len; I++) {// the inner loop is used to repeat the comparison during each round of the loop + swap for (let j = 0; j < len - 1; If j++) {/ / in front of the adjacent elements number bigger than behind the if (arr [j] > arr [j + 1]) {/ / exchange both [arr [j], arr [m + 1]] = [arr [j + 1], arr [j]]. }} // Return array arr; } // console.log(bubbleSort([3, 6, 2, 4, 1]));Copy the code

Select sort — time complexity n^2

Implement a selection sort

The implementation code is as follows:

Function selectSort(arr) {const len = arr.length; // set minIndex to let minIndex; // set minIndex to let minIndex; For (let I = 0; i < len - 1; MinIndex = I; minIndex = I; minIndex = I; For (let j = I; let j = I; j < len; If (arr[j] < arr[minIndex]) {minIndex = j; if (arr[j] < arr[minIndex]) {minIndex = j; }} // If the corresponding element of minIndex is not the current header element, swap the two elements. == i) { [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]; } } return arr; } // console.log(quickSort([3, 6, 2, 4, 1]));Copy the code

Insert sort — time complexity n^2

Implement an insert sort

The implementation code is as follows:

function insertSort(arr) {
  for (let i = 1; i < arr.length; i++) {
    let j = i;
    let target = arr[j];
    while (j > 0 && arr[j - 1] > target) {
      arr[j] = arr[j - 1];
      j--;
    }
    arr[j] = target;
  }
  return arr;
}
// console.log(insertSort([3, 6, 2, 4, 1]));
Copy the code

16 Fast queue: The time complexity ranges from nlogn to n^2

Task description: Implement a quicksort

The implementation code is as follows:

function quickSort(arr) { if (arr.length < 2) { return arr; } const cur = arr[arr.length - 1]; const left = arr.filter((v, i) => v <= cur && i ! == arr.length - 1); const right = arr.filter((v) => v > cur); return [...quickSort(left), cur, ...quickSort(right)]; } // console.log(quickSort([3, 6, 2, 4, 1]));Copy the code

17 Merge sort — time complexity nlog(n)

Implement a sorting algorithm with time complexity of N log(n)

The implementation code is as follows:

function merge(left, right) { let res = []; let i = 0; let j = 0; while (i < left.length && j < right.length) { if (left[i] < right[j]) { res.push(left[i]); i++; } else { res.push(right[j]); j++; } } if (i < left.length) { res.push(... left.slice(i)); } else { res.push(... right.slice(j)); } return res; } function mergeSort(arr) { if (arr.length < 2) { return arr; } const mid = Math.floor(arr.length / 2); const left = mergeSort(arr.slice(0, mid)); const right = mergeSort(arr.slice(mid)); return merge(left, right); } // console.log(mergeSort([3, 6, 2, 4, 1]));Copy the code

18 Binary search — time complexity log2(n)

How to determine the position of a number in an ordered array

The implementation code is as follows:

function search(arr, target, start, end) { let targetIndex = -1; let mid = Math.floor((start + end) / 2); if (arr[mid] === target) { targetIndex = mid; return targetIndex; } if (start >= end) { return targetIndex; } if (arr[mid] < target) { return search(arr, target, mid + 1, end); } else { return search(arr, target, start, mid - 1); } } // const dataArr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; // const position = search(dataArr, 6, 0, dataArr.length - 1); // if (position ! = = 1) {/ / console log (` target element in the array position: ${position} `); //} else {// console.log(" Target element is not in array "); / /}Copy the code

19 implementation LazyMan

Title description:

Implementing a LazyMan can be called as follows: LazyMan(" Hank ") output: Hi! This is Hank! LazyMan (" Hank "). Sleep (10) eat (" dinner ") output Hi! This is Hank! // Wait 10 seconds.. Wake up after 10 Eat dinner~ LazyMan(" Hank ").eat(" dinner ").eat(" supper ") output Hi This is Hank! Eat supper~ Eat supper~ LazyMan(" Hank ").eat(" supper ").sleepFirst(5) output // Wait 5 seconds Wake up after 5 Hi This is Hank! Eat supperCopy the code

The implementation code is as follows:

class _LazyMan { constructor(name) { this.tasks = []; const task = () => { console.log(`Hi! This is ${name}`); this.next(); }; this.tasks.push(task); SetTimeout (() => {// Execute this.next() after the call stack is cleared; }, 0); } next() { const task = this.tasks.shift(); // Take the first task and execute task && task(); } sleep(time) { this._sleepWrapper(time, false); return this; } sleepFirst(time) {this._sleepwrapper (time, true); return this; } _sleepWrapper(time, first) { const task = () => { setTimeout(() => { console.log(`Wake up after ${time}`); this.next(); }, time * 1000); }; if (first) { this.tasks.unshift(task); } else {this.tasks.push(task); }} eat(name) {const task = () => {console.log(' eat ${name} '); this.next(); }; this.tasks.push(task); return this; } } function LazyMan(name) { return new _LazyMan(name); }Copy the code

20 Anti-shake and throttling

Description: Handwriting anti – shake throttling

The implementation code is as follows:

// 防抖
function debounce(fn, delay = 300) {
  //默认300毫秒
  let timer;
  return function () {
    const args = arguments;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      fn.apply(this, args); // 改变this指向为调用debounce所指的对象
    }, delay);
  };
}

window.addEventListener(
  "scroll",
  debounce(() => {
    console.log(111);
  }, 1000)
);

// 节流
// 设置一个标志
function throttle(fn, delay) {
  let flag = true;
  return () => {
    if (!flag) return;
    flag = false;
    timer = setTimeout(() => {
      fn();
      flag = true;
    }, delay);
  };
}

window.addEventListener(
  "scroll",
  throttle(() => {
    console.log(111);
  }, 1000)
);
Copy the code

21 Write version sorting method

Title description: a group of version number as follows [‘ while ‘, ‘2.3.3’, ‘0.302.1’, ‘4.2’, ‘4.3.5’, ‘4.3.4.5’]. Now, it is necessary to sort the sorting result for [‘ 4.3.5 ‘, ‘4.3.4.5’, ‘2.3.3’, ‘0.302.1’, ‘while’]

The implementation code is as follows:

arr.sort((a, b) => { let i = 0; const arr1 = a.split("."); const arr2 = b.split("."); while (true) { const s1 = arr1[i]; const s2 = arr2[i]; i++; if (s1 === undefined || s2 === undefined) { return arr2.length - arr1.length; } if (s1 === s2) continue; return s2 - s1; }}); console.log(arr);Copy the code

22 LRU algorithm

Title description:

The implementation code is as follows:

// A Map object is iterated according to the order in which elements are inserted // New elements are inserted at the end of the Map, Class LRUCache {constructor(capacity) {this.secretkey = new Map(); this.capacity = capacity; } get(key) { if (this.secretKey.has(key)) { let tempValue = this.secretKey.get(key); this.secretKey.delete(key); this.secretKey.set(key, tempValue); return tempValue; } else return -1; } put(key, value) {if (this.secretkey.has (key)) {this.secretkey.delete (key); this.secretKey.set(key, value); Elseif (this.secretkey. size < this.capacity) {this.secretkey. set(key, value); } else {this.secretkey.set (key, value); This.secretkey.delete (this.secretkey.keys ().next().value); } } } // let cache = new LRUCache(2); // cache.put(1, 1); // cache.put(2, 2); / / the console. The log (" cache. Get (1) ", the cache. The get (1)) / / return 1 / / cache. The put (3, 3); // console.log("cache.get(2)", cache.get(2))// Returns -1 (not found)// cache.put(4, 4); // console.log("cache.get(1)", cache.get(1))// returns -1 (not found)// console.log("cache.get(3)", Cache. Get (3)) / / return 3. / / the console log (" cache. Get (4), "cache. Get (4)) / / return 4Copy the code

23. Implementation of Promise and related methods

Write Promise and promise.all Promise.race

The implementation code is as follows:

Class Mypromise {constructor(fn) {this.state = "pending"; This.successfun = []; // this. FailFun = []; Let resolve = (val) => {// let resolve = (val) => {// Let resolve = (val) => { == "pending") return; This. state = "success"; // In order to ensure that the then event is registered first (mainly considering synchronization code in the promise), the Promise specification here simulates asynchronous setTimeout(() => {// perform all registration functions in the current event this.successFun.forEach((item) => item.call(this, val)); }); }; let reject = (err) => { if (this.state ! == "pending") return; This. state = "fail"; SetTimeout (() => {this.failfun.foreach ((item) => {this.failfun.foreach ((item) => item.call(this, err)); }); }; // call the function try {fn(resolve, reject); } catch (error) { reject(error); Then (resolveCallback, rejectCallback) {resolveCallback = typeof resolveCallback! == "function" ? (v) => v : resolveCallback; rejectCallback = typeof rejectCallback ! == "function" ? (err) => { throw err; } : rejectCallback; Return new Mypromise((resolve, resolve)) Reject) => {this.successFun.push((val) => {try {// Execute the callback function let x = resolveCallback(val); If the result of the callback is normal, then resolve is issued to the next then chained call. If it is a Promise object, then the then method of calling X passes resolve and reject to wait for the asynchron inside X When it completes (state complete), the incoming resolve is automatically executed, thus controlling the order of chained calls x instanceof Mypromise? x.then(resolve, reject) : resolve(x); } catch (error) { reject(error); }}); This.failfun.push ((val) => {try {let x = rejectCallback(val); x instanceof Mypromise ? x.then(resolve, reject) : reject(x); } catch (error) { reject(error); }}); }); } // static all(promiseArr) {let result = []; // declare a count for each promise return with let count = 0; return new Mypromise((resolve, reject) => { for (let i = 0; i < promiseArr.length; Promise.resolve(promiseArr[I]). Then ((res) => {// We can't push the array directly Result [I] = res; count++; If (count === promise.length) {resolve(result); } }, (err) => { reject(err); }); }}); } static race(promiseArr) {return new Mypromise((resolve, reject) => {for (let I = 0; i < promiseArr.length; I ++) {promise.resolve (promiseArr[I]). Then ((res) => {// Resolve (res); }, (err) => { reject(err); }); }}); // let promise1 = new Mypromise((resolve, reject) => {// setTimeout(() => {// resolve(123); / /}, 2000); / /}); // let promise2 = new Mypromise((resolve, reject) => { // setTimeout(() => { // resolve(1234); / /}, 1000); / /}); // Mypromise.all([promise1,promise2]).then(res=>{ // console.log(res); // }) // Mypromise.race([promise1, promise2]).then(res => { // console.log(res); / /}); // promise1 // .then( // res => { // console.log(res); // return Mypromise((resolve, reject) => {// setTimeout(() => {// resolve("success")); / /}, 1000); / /}); // }, // err => { // console.log(err); // } // ) // .then( // res => { // console.log(res); / / in a second output success / /}, / / err = > {. / / the console log (err); / / / /});Copy the code

Expanded thinking: How do I cancel promises

The promise.race () method can be used to compete. Promises can be implemented by wrapping an empty Promise themselves with the Promise to be initiated

function wrap(pro) { let obj = {}; Let p1 = new promise ((resolve, reject) => {obj. Resolve = resolve; obj.reject = reject; }); obj.promise = Promise.race([p1, pro]); return obj; } let testPro = new Promise((resolve, reject) => { setTimeout(() => { resolve(123); }, 1000); }); let wrapPro = wrap(testPro); wrapPro.promise.then((res) => { console.log(res); }); Wrappro.resolve (" Intercepted ");Copy the code

24 Implement an Add method

Add (1)(2)(3)()=6 Add (1,2,3)(4)()=10

That’s the currie reduction of the function

The implementation code is as follows:

function add(... args) { let allArgs = [...args]; function fn(... newArgs) { allArgs = [...allArgs, ...newArgs]; return fn; } fn.toString = function () { if (! allArgs.length) { return; } return allArgs.reduce((sum, cur) => sum + cur); }; return fn; }Copy the code

Dynamic programming to solve coin change problem

Description: Give coins of different denominations and an amount. Write a function to calculate the minimum number of coins needed to make up the total. If no one coin combination makes up the total, return -1

Example 1: Input: Coins = [1, 2, 5], amount = 11 Output: 3 Description: 11 + 5 + 1 Example 2: Input: Coins = [2], amount = 3 Output: -1Copy the code

The implementation code is as follows:

Const coinChange = function (coins, amount) {// Const f = []; F [0] = 0; // go through [1, amount] for (let I = 1; i <= amount; F [I] = Infinity; f[I] = Infinity; f[I] = Infinity; // loop over the denomination of each available coin for (let j = 0; j < coins.length; If (i-coins [j] >= 0) {// If (i-coins [j] >= 0) {f[I] = math.min (f[I], f[i-coins [j]] + 1); If (f[amount] === Infinity) {return -1; if (f[amount] === Infinity) {return -1; } return f[amount]; };Copy the code

26 Please implement DOM2JSON a function that can output a DOM node in JSON format

Title description:

< div > < span > < a > < / a > < / span > < span > < a > < / a > < a > < / a > < / span > < / div > appeal the dom structure into the following JSON format {tag: 'div', children: [{tag: 'SPAN', children: [ { tag: 'A', children: [] } ] }, { tag: 'SPAN', children: [ { tag: 'A', children: [] }, { tag: 'A', children: [] } ] } ] }Copy the code

The implementation code is as follows:

function dom2Json(domtree) {
  let obj = {};
  obj.name = domtree.tagName;
  obj.children = [];
  domtree.childNodes.forEach((child) => obj.children.push(dom2Json(child)));
  return obj;
}
Copy the code

Extended thinking: What if I’m given an HTML string instead of a Dom tree?

So the problem is similar to template compilation in Vue where we can use the regex to match the HTML string and meet the start tag and the end tag and the text and then generate the AST and set up the parent-child relationship and advance and advance and intercept the rest of the string until the HTML has been parsed If you’re interested, check it out here

27 class array to array method

An array of classes with length attributes can be accessed using subscripts but cannot be accessed using arrays.

The implementation code is as follows:

const arrayLike=document.querySelectorAll('div') // 1. [...arrayLike] // 2.Array.from array. from(arrayLike) // 3 Array.prototype.slice.call(arrayLike) // 4.Array.apply Array.apply(null, arrayLike) // 5.Array.prototype.concat Array.prototype.concat.apply([], arrayLike)Copy the code

28 Object is implemented

Title description:

Object.is does not convert the type of the two values being compared, much like ===, although there are some differences. NaN is not equal in ===, but is equal in object. is 2. +0 and -0 are equal in ===, but are not equal in object. isCopy the code

The implementation code is as follows:

Function (x, y) {if (x === y) {if (x === y) { 1/+0 === Infinity 1/-0 === -infinity 1/-0 === -infinity == 0 || 1 / x === 1 / y; } // x ! In the case of == y, we just need to determine if it is NaN, if x! // if x and y are both NaN, return true x! == x && y ! == y; };Copy the code

29 AJAX

Title description: Using XMLHttpRequest handwritten AJAX implementation

The implementation code is as follows:

const getJSON = function (url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url, false);
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.onreadystatechange = function () {
      if (xhr.readyState !== 4) return;
      if (xhr.status === 200 || xhr.status === 304) {
        resolve(xhr.responseText);
      } else {
        reject(new Error(xhr.responseText));
      }
    };
    xhr.send();
  });
};
Copy the code

30 Sharding to solve the problem of large data rendering

Title Description: How to use sharding to optimize rendering when rendering millions of large data with simple structure

The implementation code is as follows:

let ul = document.getElementById("container"); Let total = 100000; // let once = 20; // let page = total/once; // let index = 0; Function loop(curTotal, curIndex) {if (curTotal <= 0) {return false; } // let pageCount = math.min (curTotal, once); window.requestAnimationFrame(function () { for (let i = 0; i < pageCount; i++) { let li = document.createElement("li"); li.innerText = curIndex + i + " : " + ~~(Math.random() * total); ul.appendChild(li); } loop(curTotal - pageCount, curIndex + pageCount); }); } loop(total, index);Copy the code

Extended thinking: The simple DOM structure rendering with large amount of data can be solved with the idea of fragmentation. How to deal with the complex DOM structure rendering?

At this time, we need to use the virtual list of our own baidu ha virtual list and virtual table in the daily project use is very frequent

31 Convert the virtual Dom to the real Dom

How to convert a JSON virtual Dom into a real Dom

{ tag: 'DIV', attrs:{ id:'app' }, children: [ { tag: 'SPAN', children: [ { tag: 'A', children: [] } ] }, { tag: 'SPAN', children: [ { tag: 'A', children: [] }, { tag: 'A', children: []}}}]] to appeal the virtual real Dom Dom into below < div id = "app" > < span > < a > < / a > < / span > < span > < a > < / a > < a > < / a > < / span > < / div >Copy the code

The implementation code is as follows:

Function _render(vnode) {if (typeof vnode === "number") {vnode = String(vnode); Return document.createTextNode(vnode); if (typeof vNode === "string") {return document.createTextNode(vnode); } // const DOM = document.createElement(vnode.tag); If (vnode.attrs) {// Traversing the attribute object.keys (vnode.attrs).foreach ((key) => {const value = vnode.attrs[key]; dom.setAttribute(key, value); }); ForEach ((child) => dom.appendChild(_render(child))); return dom; }Copy the code

32 Parses template strings

Title description:

Let template = 'I am {{name}}, age {{age}}, gender {{sex}}'; Let data = {name: 'name ', age: 18} render(template, data); // I am name, age 18, gender undefinedCopy the code

The implementation code is as follows:

function render(template, data) {
  let computed = template.replace(/\{\{(\w+)\}\}/g, function (match, key) {
    return data[key];
  });
  return computed;
}
Copy the code

Implement the flatten method of an object

Title description:

Const obj = {a: {b: 1, 2: c, d: {e: 5}}, b: [1, 3, 3} {2, a: b:], c: 3} flatten (obj) results returned the following / / {/ / 'a.' : 1, // 'a.c': 2, // 'a.d.e': 5, // 'b[0]': 1, // 'b[1]': 3, // 'b[2].a': 2, // 'b[2].b': 3 // c: 3 // }Copy the code

The implementation code is as follows:

function isObject(val) { return typeof val === "object" && val ! == null; } function flatten(obj) { if (! isObject(obj)) { return; } let res = {}; const dfs = (cur, prefix) => { if (isObject(cur)) { if (Array.isArray(cur)) { cur.forEach((item, index) => { dfs(item, `${prefix}[${index}]`); }); } else { for (let k in cur) { dfs(cur[k], `${prefix}${prefix ? "." : ""}${k}`); } } } else { res[prefix] = cur; }}; dfs(obj, ""); return res; } flatten();Copy the code

34 The list is transformed into a tree structure

Title description:

[{id: 1, text: 'node 1', parentId: 0}, {id: 2, text:' node 1_1', parentId: 1}, [id: 2, text: 'node 1_1', parentId: 1] [{id: 1, text: 'node 1', parentId: 0, children: [{id:2, text:' node 1_1', parentId:1}]}]Copy the code

The implementation code is as follows:

function listToTree(data) { let temp = {}; let treeData = []; for (let i = 0; i < data.length; i++) { temp[data[i].id] = data[i]; } for (let i in temp) { if (+temp[i].parentId ! = 0) { if (! temp[temp[i].parentId].children) { temp[temp[i].parentId].children = []; } temp[temp[i].parentId].children.push(temp[i]); } else { treeData.push(temp[i]); } } return treeData; }Copy the code

35 The tree structure becomes a list

Title description:

[{id: 1, text: 'node 1', parentId: 0, children: [{id:2, text:' node 1_1', parentId:1}]}] 'node 1', parentId: 0}, {id: 2, text:' node 1_1', parentId: 1}...Copy the code

The implementation code is as follows:

function treeToList(data) {
  let res = [];
  const dfs = (tree) => {
    tree.forEach((item) => {
      if (item.children) {
        dfs(item.children);
        delete item.children;
      }
      res.push(item);
    });
  };
  dfs(data);
  return res;
}
Copy the code

36 Add large numbers

Implement an Add method to add two large numbers

let a = "9007199254740991";
let b = "1234567899999999999";

function add(a ,b){
   //...
}
Copy the code

The implementation code is as follows:

Function add(a,b){// let maxLength = math.max (a.length, b.length); A = a. padstart (maxLength, 0); //"0009007199254740991" b = b.padStart(maxLength , 0); //"1234567899999999999" // define the variable used in the addition process let t = 0; let f = 0; //" let sum = ""; for(let i=maxLength-1 ; i>=0 ; i--){ t = parseInt(a[i]) + parseInt(b[i]) + f; f = Math.floor(t/10); sum = t%10 + sum; } if(f! ==0){ sum = '' + f + sum; } return sum; }Copy the code