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