Interview Collection

Interview Collection

call apply bind

//call apply bind Function.prototype.call2 = function (context) { let ctx = Object(context) || window; ctx.fn = this; let args = []; for (let i = 1; i <arguments.length; i++) { args.push(arguments[i]); } let res = ctx.fn(...args); delete ctx.fn; return res; } Function.prototype.apply2 = function (context, arr) { let ctx = Object(context) || window; ctx.fn = this; let res; if (!arr) { res = ctx.fn(); } else { let args = []; for (let i = 1; i <arguments.length; i++) { args.push(arguments[i]); } res = ctx.fn(...args); } delete ctx.fn; return res; } Function.prototype.myBind = function (oThis) { let self = this; let args = Array.prototype.slice.call(arguments, 1); let initFunc = function () {}; let fBound = function () { return self.apply(this instanceof initFunc? this: oThis, args.concat(Array.prototype.slice.call(arguments))); } initFunc.prototype = this.prototype; fBound.prototype = new initFunc(); return fBound; } Copy code

new

//new //The role of new is mainly to access the properties in the constructor and the properties in the prototype of the constructor //Use Constructor.apply(obj, arguments) to add new attributes to obj //The __proto__ property of the instance will point to the prototype of the constructor. Formally, because of this relationship, the instance obj can access the properties of the prototype of the constructor function myNew() { let obj = new Object(); let Constructor = [].shift.call(arguments); obj.__proto__ = Constructor.prototype; let res = Constructor.apply(obj, arguments); return typeof res ==='object'? res: obj; } Copy code

Array-like to array

//class array to array [...arguments]; Array.from(arguments); Array.prototype.slice.call(arguments); //Parasitic combined inheritance function prototype(child, parent) { function f() {}; f.prototype = parent.prototype; let prototype = new f(); prototype.constructor = child; child.prototype = prototype; } //Anti-shake function debounce(func, wait) { let timer; return function () { let self = this; let args = arguments; clearTimeout(timer); timer = setTimeout(() => { func.apply(self, args); }, wait); } } //Throttling function throttle(func, wait) { let start = 0; return function () { let self = this; let args = arguments; let now = +new Date(); if (now-start> wait) { func.apply(self, args); start = now; } } } function throttle(func, wait) { let timer; return function () { let self = this; let args = arguments; if (!timer) { timer = setTimeout(() => { timer = null; func.apply(self, args); }, wait); } } } //Array deduplication console.log(Array.from(new Set(arr))) console.log([...new Set(arr)]) function fn(arr) { let res = []; for (let i = 0; i <arr.length; i++) { if (!res.includes(arr[i])) { res.push(arr[i]); } } return res; } //Accurately determine the data type Object.prototype.toString.call(); /* When the toString method is called Make class the value of the internal attribute [[Class]] Finally return [object class] */ //clone function deepClone(obj) { if (typeof obj !=='object') return; let newObj = Array.isArray(obj)? []: {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { newObj[key] = typeof obj[key] ==='object'? deepClone(obj[key]): obj[key]; } } return newObj; } //jq's extend simple imitation function extend() { //Shallow copy by default let deep = false; //Target is the first parameter without passing boolean value let target = arguments[0] || {}; //Record the subscript of the object to be copied let i = 1; let options, init, copy; //If the first parameter is a boolean, then the second parameter is target if (typeof target ==='boolean') { deep = target; target = arguments[i] || {}; i++; } //If target is not an object, there is no way to copy, so set to {} if (typeof target !=='object') { target = {}; } //Loop through the objects to be copied for (; i <arguments.length; i++) { //Get the current object options = arguments[i]; //The current object cannot be empty to avoid the situation of extend(a,,b) if (options) { for (let key in options) { if (options.hasOwnProperty(key)) { //Target attribute value init = target[key]; //Object attribute value to be copied copy = options[key]; if (deep && copy && typeof copy ==='object') { target[key] = extend(deep, init, copy); } else if (copy !== undefined) { target[key] = copy; } } } } } return target; } //Find the maximum and minimum values of numbers console.log(Math.max.apply(null, arr)) console.log(Math.max.call(null, ...arr)) function fn(arr) { return arr.sort((a, b) => { return b-a; }) } //Array flattening function fn(arr) { return arr.reduce((pre, next) => { return pre.concat(Array.isArray(next)? fn(next): next); }, []) } function fn2(arr) { let res = []; for (let i = 0; i <arr.length; i++) { if (Array.isArray(arr[i])) { res = res.concat(fn2(arr[i])); } else { res = res.concat(arr[i]); } } return res; } function fn3(arr) { while (arr.some(item => Array.isArray(item))) { arr = [].concat(...arr); } return arr; } //Find the first qualified array member from front to back and find the first qualified array member from back to front //findIndex findLastIndex function createIndexFinder(e) { return function (arr, func, context) { let i = e === 1? 0: arr.length-1; for (; i >= 0 && i <arr.length; i += e) { if (func.call(context, arr[i], i, arr)) { return i } } return -1 } } //Find the position of value in a sorted array and ensure that it is inserted into the array and it is still in order function sortIndex(arr, val) { let start = 0; let end = arr.length; while (start <end) { let middle = Math.floor((start + end)/2); if (arr[middle] <val) { start = middle + 1; } else { end = middle; } } arr.splice(end, 0, val); return arr } //Array out of order /* The original sort sort realizes that the array is not completely out of order V8 uses insertion sort when the target array length is less than 10 when processing sort, and vice versa, uses a mixed sort of fast sort and insertion sort The fundamental reason is: in the insertion sort algorithm, when the elements to be sorted are compared with the ordered elements, once the position is determined, it will not be compared with the ordered elements before the position, which leads to incomplete disorder. */ function Random(arr) { for (let i = arr.length; i> 0; i--) { let j = Math.floor(Math.random() * i); [arr[i-1], arr[j]] = [arr[j], arr[i-1]]; } return arr; } //Function Currying function curry(fn, args) { let length = fn.length; let theArgs = args || []; return function () { let newArgs = theArgs.concat(Array.prototype.slice.call(arguments)); if (newArgs.length <length) { return curry.call(this, fn, newArgs); } else { return fn.apply(this, newArgs); } } } //Binary search function fn(arr, val) { let start = 0; let end = arr.length; while (start <= end) { let middle = Math.floor((start + end)/2); if (arr[middle] === val) { return middle; } else if (arr[middle]> val) { end = middle-1; } else if (arr[middle] <val) { start = middle + 1; } } return -1 } //Bubble Sort function sort(arr) { for (let i = 0; i <arr.length; i++) { for (let j = 0; j <arr.length-i-1; j++) { if (arr[j + 1] <arr[j]) { [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; } } } return arr } //Quick sort function fn(arr) { if (arr.length <= 1) { return arr; } let middle = Math.floor(arr.length/2); let middleVal = arr.splice(middle, 1)[0]; let leftArr = [], rightArr = []; for (let i = 0; i <arr.length; i++) { if (arr[i] <middleVal) { leftArr.push(arr[i]); } else { rightArr.push(arr[i]); } } return fn(leftArr).concat(middleVal, fn(rightArr)); } //Insertion sort function fn(arr) { for (let i = 1; i <arr.length; i++) { let compare = arr[i]; let j = i-1; while (arr[j]> compare) { arr[j + 1] = arr[j]; j--; } arr[j + 1] = compare; } return arr } //Use reduce method to implement map function fn(arr, cb, ctx) { return arr.reduce((pre, cur, index, array) => { pre[index] = cb.call(ctx, cur, index, array); return pre; }, []) } //Write a random number that generates min to max function Random(min, max) { return Math.floor(Math.random() * (max-min + 1)) + min; } //The sleep function outputs 1 after 1s and outputs 3 after 3s and outputs 2 after 2s let arr = [1, 3, 2]; async function fn(arr) { for (let i = 0; i <arr.length; i++) { await new Promise((resolve) => { setTimeout(() => { console.log(arr[i]); resolve(); }, arr[i] * 1000); }) } } //A random array of integers, one of the numbers appears alone, and all the others appear in pairs, find out the number that appears alone function fn(arr) { let res = arr[0]; for (let i = 1; i <arr.length; i++) { res ^= arr[i] } return res } /** * Create a repeat function function repeat(func,times,wait) {}; * Enter const repeatFunc = repeat(alert,4,3000); * Execute repeatFunc('helloworld'); * Alert 4 times helloworld every 3 seconds */ function repeat(func, times, wait) { return function (str) { let count = 0; let timer = setInterval(() => { count++; func(str); if (count === times) { clearInterval(timer) } }, wait) } } //Fibonacci sequence, one person goes upstairs, one step can go up 2 steps or 1 step. If there are N steps, how many ways are there? //use tail recursive call function fib(n, a = 1, b = 1) { if (n <= 1) return b; return fib(n-1, b, a + b) } //Imitate underscore to implement a template engine function fn(tpl, data) { let tplArr = tpl.split(/(\<%=?|%\>)/gm); let funcBody = ["with(this){let result = [];"]; let code = 0; for (let i = 0; i <tplArr.length; i++) { if (tplArr[i] ==='<%') { code = 1; continue; } else if (tplArr[i] ==='<%=') { code = 2; continue; } else if (tplArr[i] ==='%>') { code = 0; continue; } if (code === 1) { funcBody.push(tplArr[i]); } else if (code === 2) { funcBody.push("result.push("); funcBody.push(tplArr[i]); funcBody.push(");"); } else if (code === 0) { funcBody.push("result.push(\""); funcBody.push(tplArr[i]); funcBody.push("\");"); } funcBody.push("return result.join('');}"); let res = new Function(funcBody.join("")); return res.call(data); } } //Implement a custom function function Event() { this.handlers = {}; this.on = function (type, handler, once = false) { if (!this.handlers[type]) { this.handlers[type] = []; } if (!this.handlers[type].includes(handler)) { this.handlers[type].push(handler); handler.noce = once; } } this.off = function (type, handler) { if (!this.handlers[type]) { this.handlers[type] = []; } else { this.handlers[type] = this.handlers[type].filter((fn) => { return fn !== handler; }) } } this.trigger = function (type, eventData) { if (this.handlers[type]) { this.handlers[type].forEach((fn) => { fn.call(this, eventData); if (fn.once) { this.off(type, fn); } }) } } this.once = function (type, handler, once = true) { this.on(type, handler, once); } } //Implement LazyMan function (function (window) { let taskList = []; function subscribe() { let args = Array.prototype.slice.call(arguments); let params = {}; params.handle = args[0]; params.handleData = args.slice(1); if (params.handle ==='sleepFirst') { taskList.unshift(params); } else { taskList.push(params); } } function publish() { if (taskList.length) { run(taskList.shift()); } } function run(options) { let handle = options.handle; let handleData = options.handleData; if (handle ==='lazyMain') { lazyMain.apply(null, handleData); } else if (handle ==='eat') { eat.apply(null, handleData); } else if (handle ==='sleep') { sleep.apply(null, handleData); } else { sleepFirst.apply(null, handleData); } } function LazyMan() {} LazyMan.prototype.eat = function (str) { subscribe('eat', str); return this; } LazyMan.prototype.sleep = function (delay) { subscribe('sleep', delay); return this; } LazyMan.prototype.sleepFirst = function (delay) { subscribe('sleepFirst', delay); return this; } function lazyMain(str) { console.log('lazyMain', str); publish(); } function eat(str) { console.log('eat', str); publish(); } function sleep(delay) { setTimeout(() => { console.log('sleep', delay); publish(); }, delay * 1000); } function sleepFirst(delay) { setTimeout(() => { console.log('sleepFirst', delay); publish(); }, delay * 1000); } window.LazyMan = function (str) { subscribe('lazyMain', str); setTimeout(() => { publish(); }, 0); return new LazyMan(); } })(window); //Given an unordered, non-repeated array data, randomly extract n numbers, add them to sum, and list all combinations function fn(arr, n, sum) { let resArr = []; function handle(arr, n, res, start) { if (res.length === n) { return resArr.push(res); } if (start === arr.length) { return; } handle(arr, n, res.slice(), start + 1); res.push(arr[start]); handle(arr, n, res, start + 1); } handle(arr, n, [], 0); let finaArr = []; let reducer = (pre, next) => pre + next; for (let i = 0; i <resArr.length; i++) { let item = resArr[i].reduce(reducer); if (item === sum) { finaArr.push(resArr[i]); } } return finaArr; } //implement instanceof function fn(left, right) { if (typeof left !== "object" || left === null) { return false; } let proto = Object.getPrototypeOf(left); while (true) { if (proto === null) return false; if (proto === right.prototype) return true; proto = Object.getPrototypeOf(proto); } } //Native js implements the map method function Map(arr, cb) { let res = []; for (let i = 0; i <arr.length; i++) { let result = cb.call(this, arr[i], i, arr); res.push(result); } return res; } //Tower of Hanoi output moving steps function hano(n, a, b, c) { if (n === 1) { console.log(`move ${n} from ${a} to ${c}`); } else { hano(n-1, a, c, b); console.log(`move ${n} from ${a} to ${c}`); hano(n-1, b, a, c); } } //There are unequal integers in an array, given a specific value, output the first two values in the array and the number equal to the specific value function fn(arr, val) { for (let i = 0; i <arr.length; i++) { let res = val-arr[i]; let index = arr.indexOf(res) if (index !== -1) { return [i, index]; } } } //Find the longest common substring of two strings function fn(str1, str2) { for (let i = str2.length; i> 0; i--) { for (let j = 0; j + i <= str2.length; j++) { let substring = str2.substring(j, j + i); if (str1.includes(substring)) { return substring } } } } //Binary tree traversal function fn(root) { console.log(root.val); if (root.left) { fn(root.left) } if (root.right) { fn(root.right) } } //Binary tree sequence traversal function fn(root) { let res = []; let tree = []; tree.push(root); while (tree.length) { let node = tree.shift(); res.push(node.val); if (node.left) { tree.push(node.left); } if (node.right) { tree.push(node.right) } } return res; } //Get the maximum depth of the binary tree function fn(root) { const handle = (node, deep) => { if (!node) { return deep } let left = handle(node.left, deep + 1); let right = handle(node.right, deep + 1); return Math.max(left, right) } return handle(root, 0) } //Output the viewpoint that can be seen from the left perspective of the binary tree function fn(root) { let res = []; const handle = (node, index) => { if (!node) { return } if (!res[index]) { res[index] = node.val; } handle(node.left, index + 1); handle(node.right, index + 1); } handle(root, 0); return res; } //Give a binary tree and a value, check whether there is a path in the binary tree, and all the values on this path add up to the given value, and output the path function fn(root, sum) { let curSum = 0; let path = []; let res = []; function handle(root, sum, curSum, path, res) { curSum += root.val; path.push(root.val); if (curSum === sum && !root.left && !root.right) { res.push(path.slice()); } if (root.left) { handle(root.left, sum, curSum, path, res); } if (root.right) { handle(root.right, sum, curSum, path, res); } //It is equivalent to not fulfilling the condition after touching the bottom of the binary tree and then returning to the previous level to calculate again path.pop(); } handle(root, sum, curSum, path, res); return res; } //Determine if array B is a subset of array A function fn(arr1, arr2) { while (arr1.length) { return arr2.includes(arr1.pop()); } return false } //Exchange two values without third-party variables function fn(a, b) { a = a + b; b = a-b; a = a-b; return [a, b]; } //Array full row function fn(arr) { let res = []; let cur = []; function handle(arr) { let init; for (let i = 0; i <arr.length; i++) { init = arr.splice(i, 1)[0]; cur.push(init); if (arr.length === 0) { res.push(cur.slice()) } handle(arr); arr.splice(i, 0, init); cur.pop(); } return res; } return handle(arr) } //Addition of two large integers function add(a, b) { let res =''; let temp = 0; a = a.split(''); b = b.split(''); while (a.length || b.length || temp) { temp += ~~a.pop() + ~~b.pop(); res = temp% 10 + res; temp = temp> 9; } return res; } //Multiple asynchronous concurrency control, batch request data, control concurrency through the max parameter, and execute the callback function when all requests are over function sendRequest(urls, max, cb) { let curIndex = 0; let urlsObj = {}; let times = Math.ceil(urls.length/max); for (let i = 0; i <times; i++) { urlsObj[i] = urls.slice(i * max, (i + 1) * max); } let getFetch = (source) => { return source.map((item) => { return fetch(item).then((res) => { return res.blob(); }) }) } let send = () => { urlsObj[curIndex] && Promise.all(getFetch(urlsObj[curIndex])).then((res) => { curIndex++; console.log(`The ${curIndex} request`, res); if (curIndex === times) { cb(); } send(); }) } send(); } //Implement the following function, request data in batches, and control concurrency through the max parameter. To send max first, add one to the http queue if one of them is returned, and so on, and finally return all the results function handleRequest(arr, max, cb) { let ajaxNum = 0; let length = arr.length; let result = []; const getFetch = (url) => { return new Promise((resolve) => { fetch(url).then((res) => { resolve(res.blob()); }) }) } const handle = (urls) => { while (ajaxNum <= max && urls.length) { ajaxNum++; getFetch(urls.shift()).then((res) => { result.push(res); handle(urls); }).catch((err) => { console.log(err); }).finally(() => { ajaxNum--; result.length === length && typeof cb ==='function' && cb(result); }) } } handle(arr); } //Implement a simple version of the promise function myPromise(constructor) { let self = this; self.status ='pending'; self.value = undefined; self.reason = undefined; self.onResolveQueue = []; self.onRejectQueue = []; function resolve(value) { if (self.status ==='pending') { self.status ='resolve'; self.value = value; setTimeout(() => { self.onResolveQueue.forEach(resolve => resolve(value)); }, 0); } } function reject(reason) { if (self.status ==='pending') { self.status ='reject'; self.reason = reason; setTimeout(() => { self.onRejectQueue.forEach(reject => reject(reason)); }, 0); } } try { constructor(resolve, reject); } catch (e) { reject(e); } } myPromise.prototype.then = function (onFulfilled, onRejected) { if (this.status ==='resolve') { onFulfilled(this.value); } else if (this.status ==='reject') { onRejected(this.reason); } else if (this.status ==='pending') { this.onResolveQueue.push(onFulfilled); this.onRejectQueue.push(onRejected); } return this; } //implement promiseAll function promiseAll(arr) { return new Promise((resolve, reject) => { let count = 0; let resArr = []; for (let i = 0; i <arr.length; i++) { arr[i].then((res) => { count++; resArr.push(res); if (count === arr.length) { return resolve(resArr); } }).catch((err) => { console.log(err); }) } }) } //implement promiseRace function promiseRace(arr) { return new Promise((resolve, reject) => { arr.forEach((item) => { item.then(resolve, reject); }) }) } //Adaptive two-column width fixed layout in the middle /** * .container{ display: flex; } .left,.right{ width: 200px; height: 500px; } .left{ background: red; } .right{ background: green; } .middle{ background: gray; } .middle{ flex-grow: 1; } */ /** * .middle{ width: 100%; height: 200px; background: gray; padding: 0 200px; } .left{ position: absolute; top: 0; left: 0; width: 200px; height: 200px; background: red; } .right{ position: absolute; top: 0; right: 0; width: 200px; height: 200px; background: green; } */ //The element is centered horizontally and vertically /** * 1, the parent element * display: flex; justify-content: center; align-items: center; 2. Sub-elements position: absolute; top: 50%; left: 50%; margin-left: -100px; margin-top: -100px; 3. Sub-elements position: absolute; top: 50%; left: 50%; transform: translateX(-50%) translateY(-50%); 4. Parent element display: table-cell; vertical-align: middle; Child element margin: 0 auto; 5. Sub-elements position: absolute; top: 0; left: 0; right: 0; bottom: 0; margin: auto; */ //To achieve such a layout, no matter how the width and height of the outer container change, the yellow area is always vertically centered relative to the outer container, with a distance of 20px between the left and right, and the height of the yellow area is always 50% of its own width /** * .container{ width: 500px; height: 500px; border: 1px solid red; display: flex; justify-content: center; align-items: center; padding: 0 20px; box-sizing: border-box; } .main{ width: 100%; padding-top: 50%; background: yellow; } */ //Coin change greedy algorithm function coinChange(arr, val) { arr = arr.sort((a, b) => { return b-a; }) let res = []; let sum = 0; function handle(val) { for (let i = 0; i <arr.length; i++) { if (sum + arr[i] <= val) { res.push(arr[i]); sum += arr[i]; } } } handle(val); return res; } //Simple jsonp function jsonp(url, cb) { const script = document.createElement('script'); script.src = `${url}&cb=${cb}`; document.body.appendChild(script); window[cb] = (res) => { console.log(res) } } //Find the maximum sum of consecutive sub-arrays of the array function fn(arr) { let sum = arr[0]; let max = arr[0]; for (let i = 1; i <arr.length; i++) { sum = Math.max(sum + arr[i], arr[i]); max = Math.max(sum, max); } return max; } //Singleton mode example global modal const createModal = (function () { let modal = null; return function (content) { if (!modal) { modal = document.createElement('div'); modal.id ='modal'; modal.style.display ='none'; modal.innerHTML = content; document.body.appendChild(modal); } return modal } })() //Given an array containing n positive integers and a positive integer s, find the continuous sub-array with the smallest length satisfying its sum s and return its length. If there is no matching sub-array, 0 is returned. function fn(arr, s) { let minLength = Infinity; let i = 0; let j = 0; let sum = 0; while (i <arr.length) { sum += arr[i]; while (sum >= s) { minLength = Math.min(minLength, i-j + 1); sum -= arr[j]; j++; } i++; } return minLength === Infinity? 0: minLength; } //Given a set of non-negative integer nums, rearrange the order of each number of them (each number cannot be split) to form the largest integer. Note: The output may be very large, so you need to return a string instead of an integer. function fn(arr) { arr.sort((a, b) => { let num1 = `${a}${b}`; let num2 = `${b}${a}`; return num2-num1; }); return arr.length? arr.join(''): '0'; } //Find the most consecutive characters and the number of characters in the string function fn(str) { let strArr = str.split(''); let s = strArr[0]; let res = []; for (let i = 1; i <= strArr.length; i++) { if (s.indexOf(strArr[i]) !== -1) { s += strArr[i] } else { res.push(s); s = strArr[i] } } res = res.sort((a, b) => { return b.length-a.length; }) return `Sequential string ${Array.from(new Set(res[0]))[0]} appears the most times, ${res[0].length} times` } //palindrome string function fn(str) { let str1 = str.toLowerCase(); let str2 = str1.split('').reverse().join(''); return str1 === str2; } Copy code