preface
A few weeks ago in the job hunting, brush more than 100 topics, here is a summary
1. Realize the curry
Bigfrontend. Dev/useful/problem /…
const join = (a, b, c) = > {
return `${a}_${b}_${c}`
}
const curriedJoin = curry(join)
curriedJoin(1.2.3) / / '1 _2_3'
curriedJoin(1) (2.3) / / '1 _2_3'
curriedJoin(1.2) (3) / / '1 _2_3'
/ / implementation of curry
const curry = (fn, ... initParams) = > {
return (. args) = > {
return ((params) = > {
returnparams.length >= fn.length ? fn(... params) : curry(fn, ... params) })([ ...initParams, ...args]) } }Copy the code
2. Implement curry() with placeholder support
Bigfrontend. Dev/useful/problem /…
/** * merge arguments (replace placeholders) */
function merge(params1, params2) {
for (let i = 0; i < params1.length; i += 1) {
if (params2.length) {
if (typeof params1[i] === 'symbol') {
const first = params2.shift()
params1[i] = first
}
} else {
break}}return [...params1, ...params2]
}
/ * * *@param { (...args: any[]) => any } fn
* @returns { (...args: any[]) => any }* /
function curry(fn, ... initParams) {
return (. args) = > {
const params = merge([...initParams], [...args])
return ((params) = > {
params = params.slice(0, fn.length)
// Check whether it can be executed
const isCall = params.filter((item) = > typeofitem ! = ='symbol').length >= fn.length
returnisCall ? fn(... params) : curry(fn, ... params) })(params) } } curry.placeholder =Symbol(a)Copy the code
3. Realize the Array. The prototype. Flat ()
Bigfrontend. Dev/useful/problem /…
/ * * *@param { Array } arr
* @param { number } depth
* @returns { Array }* /
function flat(arr, depth = 1) {
const result = []
if (depth) {
let isExistArray = false;
for (let i = 0; i < arr.length; i += 1) {
const item = arr[i]
if (Array.isArray(item)) {
isExistArray = trueresult.push(... item) }else {
result.push(item)
}
}
if (isExistArray) {
return flat(result, depth - 1)}else {
return result
}
} else {
return arr
}
}
Copy the code
4. Write a throttle ()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {Function} func
* @param {number} wait* /
function throttle(func, wait) {
let timer
let lastArgs
return function (. param) {
if(! timer) { func.call(this. param) timer =window.setTimeout(() = > {
lastArgs && func.call(this. lastArgs) lastArgs =null
timer = null
}, wait)
} else {
lastArgs = [...param]
}
}
}
Copy the code
6. Write a debounce ()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {Function} func
* @param {number} wait* /
function debounce(func, wait) {
let timer
return function (. param) {
function clear() {
window.clearTimeout(timer)
timer = null
}
function run() {
timer = window.setTimeout(() = > {
func.call(this. param) clear() }, wait) }if(! timer) { run() }else {
clear()
run()
}
}
}
Copy the code
8. Shuffle an array randomly by hand ()
Bigfrontend. Dev/useful/problem /…
Regular const randomIndex = math.floor (math.random () * arr.length) generates a random index in a way that is not random enough
/ * * *@param {any[]} arr* /
function shuffle(arr) {
for (let i = 0; i < arr.length; i += 1) {
const j = i + Math.floor(Math.random() * (arr.length - 1));
[arr[i], arr[j]] = [arr[j], arr[i]]
}
return arr
}
Copy the code
9. Decrypt the message
Bigfrontend. Dev/useful/problem /…
/ * * *@param {string[][]} message
* @return {string}* /
function decode(message) {
// Empty judgment
if(! message.length || ! message[0].length) {
return ' '
}
let power = true
let str = ' '
let i = 0
let j = 0
let direction = 'LowerRight' // LowerRight | UpperRight
let w = message[0].length
let h = message.length
function lowerRight() {
if (i + 1 < h && j + 1 < w) {
i = i + 1
j = j + 1
} else {
if (i - 1 > 0 && j + 1 < w) {
direction = 'UpperRight'
i = i - 1
j = j + 1
} else {
power = false}}}function upperRight() {
if (i - 1 > 0 && j + 1 < w) {
i = i - 1
j = j + 1
} else {
if (i + 1 < h && j + 1 < w) {
direction = 'LowerRight'
i = i + 1
j = j + 1
} else {
power = false}}}while (power) {
str += message[i][j]
if (direction === 'LowerRight') {
lowerRight()
} else if (direction === 'UpperRight') {
upperRight()
}
}
return str
}
Copy the code
10. Find the first bad version
Bigfrontend. Dev/useful/problem /…
Simple binary search
/* type TypIsBad = (version: number) => boolean */
/ * * *@param {TypIsBad} isBad
*/
function firstBadVersion(isBad) {
return (version) = > {
let start = 0
let end = version
let result = isBad(version) ? version : -1
while (end >= start) {
let midd = Math.floor((start + end) / 2)
if (isBad(midd)) {
// If it is bad
end = midd - 1
result = midd
} else {
// If it is good
start = midd + 1}}return result
}
}
Copy the code
11. What is Composition? Implement pipe ()
Bigfrontend. Dev/useful/problem /…
Implement a pipe function
/ * * *@param {Array<(arg: any) => any>} funcs
* @return {(arg: any) => any}* /
function pipe(funcs) {
return function (arg) {
let param = arg
for (let i = 0; i < funcs.length; i += 1) {
const func = funcs[i]
param = func(param)
}
return param
}
}
Copy the code
Create a Queue using a Stack.
Bigfrontend. Dev/useful/problem /…
You can implement a Queue with two stacks
An easier way is to store the enqueue backwards every time.
class Stack {
constructor () {
this.stack = []
}
push(element) {
this.stack.push(element)
}
peek() {
return this.stack[this.stack.length - 1]}pop() {
return this.stack.pop()
}
size() {
return this.stack.length
}
}
// Implement Queue with Stack
class Queue {
constructor () {
this.enqueueStack = new Stack()
this.dequeueStack = new Stack()
}
_enqueueSyncDequeue () {
const dequeueTemp = new Stack()
const enqueueTemp = new Stack()
while (this.enqueueStack.size()) {
const p = this.enqueueStack.pop()
dequeueTemp.push(p)
enqueueTemp.push(p)
}
while (enqueueTemp.size()) {
this.enqueueStack.push(enqueueTemp.pop())
}
this.dequeueStack = dequeueTemp
}
_dequeueSyncEnqueue () {
const dequeueTemp = new Stack()
const enqueueTemp = new Stack()
while (this.dequeueStack.size()) {
const p = this.dequeueStack.pop()
dequeueTemp.push(p)
enqueueTemp.push(p)
}
while (dequeueTemp.size()) {
this.dequeueStack.push(dequeueTemp.pop())
}
this.enqueueStack = enqueueTemp
}
enqueue(element) {
this.enqueueStack.push(element)
this._enqueueSyncDequeue()
}
peek() {
return this.dequeueStack.peek()
}
dequeue() {
const p = this.dequeueStack.pop()
this._dequeueSyncEnqueue()
return p
}
size() {
return this.enqueueStack.size()
}
}
/ / improved version
class Queue {
constructor () {
this.stack = new Stack()
this.queue = new Stack()
}
enqueue(element) {
while (this.queue.size()) {
this.stack.push(this.queue.pop())
}
this.queue.push(element)
while (this.stack.size()) {
this.queue.push(this.stack.pop())
}
}
peek() {
return this.queue.peek()
}
dequeue() {
return this.queue.pop()
}
size() {
return this.queue.size()
}
}
Copy the code
14. To achievememo()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {Function} func
* @param {(args:[]) => string } [resolver] - cache key generator
*/
function memo(func, resolver) {
const map = new Map(a);return function (. params) {
let key
if (typeof resolver === 'function') { key = resolver(... params) }else {
key = [...params].join(The '-')}if (map.has(key)) {
return map.get(key)
} else {
const val = func.apply(this, [...params])
map.set(key, val)
return val
}
}
}
Copy the code
15. Implement jquery-like DOM Wrapper
Bigfrontend. Dev/useful/problem /…
/ * * *@param {HTMLElement} el - element to be wrapped
*/
function $(el) {
el.css = function (key, value) {
el.style[key] = value
return el
}
return el
}
Copy the code
Implement an Event Emitter
Bigfrontend. Dev/useful/problem /…
// please complete the implementation
class EventEmitter {
constructor () {
this.map = {}
}
subscribe(eventName, callback) {
const event = {eventName, callback}
const that = this
if (this.map[eventName]) {
this.map[eventName].push(event)
} else {
this.map[[eventName]] = [event]
}
return{ release () { that.map = { ... that.map, [eventName]: that.map[eventName].filter((e) = >e ! == event) } } } }emit(eventName, ... args) {
if (this.map[eventName]) {
this.map[eventName].forEach((event) = > {
const{ callback } = event callback(... args) }) } } }Copy the code
17. Implement a DOM Element Store
Bigfrontend. Dev/useful/problem /…
Notice the time space complexity, the has method should be o(1)
How to implement a Map polyfill
class NodeStore {
constructor () {
this.map = {}
}
/ * * *@param {Node} node
* @param {any} value* /
set(node, value) {
if(! node.__mapKey__) { node.__mapKey__ =Symbol(a)this.map[node.__mapKey__] = value
} else {
this.map[node.__mapKey__] = value
}
}
/ * * *@param {Node} node
* @return {any}* /
get(node) {
return this.map[node.__mapKey__]
}
/ * * *@param {Node} node
* @return {Boolean}* /
has(node) {
return!!!!! node.__mapKey__ && node.__mapKey__in this.map
}
}
Copy the code
Optimize a function
Bigfrontend. Dev/useful/problem /…
Time complexity before optimization O(m * n)
// Items is an array
// Contains elements with >=3 attributes
let items = [
{color: 'red'.type: 'tv'.age: 18},
{color: 'silver'.type: 'phone'.age: 20},
{color: 'blue'.type: 'book'.age: 17}]// An array of keys and values
const excludes = [
{k: 'color'.v: 'silver'},
{k: 'type'.v: 'tv'},... ]function excludeItems(items, excludes) {
excludes.forEach( pair= > {
items = items.filter(item= > item[pair.k] === item[pair.v])
})
return items
}
Copy the code
After the optimization:
function excludeItems(items, excludes) {
const excludesMap = {}
excludes.forEach(({k, v}) = > {
if (excludesMap[k]) {
excludesMap[k].add(v)
} else {
excludesMap[k] = new Set()
excludesMap[k].add(v)
}
})
return items.filter((item) = > {
return Object.keys(item).every((key) = > {
if (excludesMap[key]) {
return! excludesMap[key].has(item[key]) }return true})})}Copy the code
19. Search for the corresponding node in the DOM tree with the same structure
Bigfrontend. Dev/useful/problem /…
/ * * *@param {HTMLElement} rootA
* @param {HTMLElement} rootB - rootA and rootB are clone of each other
* @param {HTMLElement} nodeA* /
const findCorrespondingNode = (rootA, rootB, target) = > {
const paths = []
let isSearchEnd = false
let targetB = rootB
const find = (node, index) = > {
if(index ! = =undefined && !isSearchEnd) {
paths.push(index)
}
if(node ! == target) {const children = [...node.children]
children.forEach((item, index) = > {
find(item, index)
})
if(! isSearchEnd) { paths.pop() } }else {
isSearchEnd = true
}
}
find(rootA)
if(paths.length ! = =0) {
while (paths.length) {
const index = paths.shift()
targetB = [...targetB.children][index]
}
}
return targetB
}
Copy the code
20. Check data Type
Bigfrontend. Dev/useful/problem /…
/ * * *@param {any} data
* @return {string}* /
function detectType(data) {
if(data instanceof FileReader) {
return 'object'
}
const type = Object.prototype.toString.call(data);
return /^\[object\s+([A-Za-z]+)\]$/.exec(type) [1].toLocaleLowerCase()
}
Copy the code
21. The handwritten JSON. Stringify ()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {any} data
* @return {string}* /
function stringify(data) {
if(typeof data === 'bigint') {
throw new Error()}if(typeof data === 'string') {
return `"${data}"`
}
if(typeof data === 'function') {
return undefined;
}
if(data ! == data) {return 'null'
}
if(data === Infinity) {
return 'null'
}
if(data === -Infinity) {
return 'null'
}
if(typeof data === 'number') {
return `${data}`
}
if(typeof data === 'boolean') {
return `${data}`
}
if(data === null) {
return 'null'
}
if(data === undefined) {
return 'null'
}
if(typeof data === 'symbol') {
return 'null'
}
if(data instanceof Date) {
return `"${data.toISOString()}"`
}
if (Array.isArray(data)) {
const arr = data.map((item) = > stringify(item))
return ` [${arr.join(', ')}] `
}
if (typeof data === 'object') {
const arr = []
Object.entries(data).forEach(([key, value]) = > {
if(value ! = =undefined) {
arr.push(`"${key}":${stringify(value)}`)}})return ` {${arr.join(', ')}} `}}Copy the code
22. The handwritten JSON. The parse ()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {any} data
* @return {string}* /
function parse(data) {
function equal(text) {
if(text && text ! == current) {throw new Error()}return true
}
function next() {
current = text.charAt(index)
index += 1
return current
}
function white() {
while (current && current == ' ') {
next()
}
}
function object() {
let key
let obj = Object.create(null)
if (current === '{') {
next()
white()
if (current === '} ') {
next()
return obj
}
while (current) {
key = string(a)// Reads the next non-empty character
white()
// The next non-null character should be ":", otherwise an error is thrown
equal(':')
next()
obj[key] = value()
// Reads the next non-empty character
white()
if (current === '} ') {
next()
return obj
}
// If not '}', the next character should be ',', otherwise an error is thrown
equal(', ')
// Reads the next non-empty character
white()
}
}
throw new Error()}function string() {
let str = ' '
if (current === '"') {
let startIndex = index
while (next()) {
if (current === '"') {
if (index - 1 > startIndex) {
str += text.substring(startIndex, index - 1)
}
next()
return str
}
}
} else {
throw new Error()}}function array() {
let arr = []
if (current === '[') {
next()
// Reads the next non-empty string
white()
if (current === '] ') {
next()
return arr
}
while (current) {
// Read the contents of the array
arr.push(value())
// Reads the next character
white()
if (current === '] ') {
next()
return arr
}
equal(', ')
next()
white()
}
}
throw new Error()}function number() {
let number = ' '
let string = ' '
if (current === The '-') {
string = ' '
next()
}
let temp = Number(current)
while (temp >= 0 && temp <= 9 && current) {
string += current
next()
temp = Number(current)
}
if (current === '. ') {
string+ ='. '
next()
temp = Number(current)
while (temp >= 0 && temp <= 9 && current) {
string += current
next()
temp = Number(current)
}
}
number = Number(string)
return number
}
function word() {
switch (current) {
case 't':
next()
equal('r')
next()
equal('u')
next()
equal('e')
next()
return true
case 'f':
next()
equal('a')
next()
equal('l')
next()
equal('s')
next()
equal('e')
next()
return false
case 'n':
next()
equal('u')
next()
equal('l')
next()
equal('l')
next()
return null
}
throw new Error()}function value() {
white()
switch (current) {
// If it is an object
case '{':
return object(a)// If it is an array
case '[':
return array()
// If it is a string
case '"':
return string(a)// If it contains a minus sign, it is a number
case "-":
return number(a)default:
let temp = Number(current)
if (temp >= 0 && temp <= 9) {
return number()}else {
return word()
}
}
}
let text = data + ' '
let index = 0
let current = ' '
let result = value()
white()
if (current) {
throw new Error()}return result
}
Copy the code
23. Implement a sum() method
Bigfrontend. Dev/useful/problem /…
/ * * *@param {number} num* /
function sum(num) {
const fn = function (arg) {
return sum(num + arg)
}
fn.toString = function () {
return num
}
return fn
}
Copy the code
24. Write a Priority Queue in JavaScript
Bigfrontend. Dev/useful/problem /…
// complete the implementation
class PriorityQueue {
/ * * *@param {(a: any, b: any) => -1 | 0 | 1} compare -
* compare function, similar to parameter of Array.prototype.sort
*/
constructor(compare) {
this.compare = compare;
}
/** * return {number} amount of items */
size(){}/** * returns the head element */
peek(){}/ * * *@param {any} element - new element to add
*/
add(element){}/**
* remove the head element
* @return {any} the head element
*/
poll(){}}Copy the code
25. Update the array order
Bigfrontend. Dev/useful/problem /…
/ * * *@param {any[]} items
* @param {number[]} newOrder
* @return {void}* /
// No extra space is needed
function sort(items, newOrder) {
// Use simple bubble sort
for (let i = 0; i < items.length; i += 1) {
for (let j = i + 1; j < items.length; j += 1) {
if (newOrder[i] > newOrder[j]) {
// Update the order of items and the order of newOrder
let otemp = newOrder[j]
let itemp = items[j]
newOrder[j] = newOrder[i]
newOrder[i] = otemp
items[j] = items[i]
items[i] = itemp
}
}
}
return items
}
Copy the code
26. The realization of the Object. The assign ()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {any} target
* @param {any[]} sources
* @return {object}* /
function objectAssign(target, ... sources) {
if (target === null || target === undefined) {
throw new Error()}if (typeof target === 'number') {
target = new Number(target)
}
if (typeof target === 'boolean') {
target = new Boolean(target)
}
if (typeof target === 'string') {
target = new String(target)
}
sources.forEach(source= > {
if (source === undefined || source === null) {
return
}
Object.defineProperties(
target,
Object.getOwnPropertyDescriptors(source)
)
})
return target
}
Copy the code
27. Achieve completeAssign ()
Bigfrontend. Dev/useful/problem /…
Developer.mozilla.org/en-US/docs/…
function completeAssign(target, ... sources) {
if (target === null || target === undefined) {
throw new Error()}if (typeof target === 'number') {
target = new Number(target)
}
if (typeof target === 'boolean') {
target = new Boolean(target)
}
if (typeof target === 'string') {
target = new String(target)
}
sources.forEach(source= > {
if (source === undefined || source === null) {
return
}
Object.defineProperties(
target,
Object.getOwnPropertyDescriptors(source)
)
})
return target
}
Copy the code
28. Achieve clearAllTimeout ()
Bigfrontend. Dev/useful/problem /…
const beforeSetTimeout = window.setTimeout
window.timers = new Set(a)/ / rewrite setTimeout
window.setTimeout = function (handler, timeout, ... arg) {
const that = this
const timer = beforeSetTimeout(
function (. arg) { handler.apply(that, [...arg]) }, timeout, ... arg )window.timers.add(timer)
return timer
}
/** * cancel all timer from window.setTimeout */
function clearAllTimeout() {
window.timers.forEach((timer) = > {
window.clearTimeout(timer)
})
}
Copy the code
Implement Async Helper –sequence()
Bigfrontend. Dev/useful/problem /…
/* type Callback = (error: Error, data: any) => void type AsyncFunc = ( callback: Callback, data: any ) => void */
function promisify(func) {
return function (num) {
return new Promise(function(resolve, reject) {
func(function (err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
}, num)
})
}
}
/ * * *@param {AsyncFunc[]} funcs
* @return {(callback: Callback) => void}* /
function sequence(funcs) {
funcs = funcs.map(func= > promisify(func))
return async function (callback, data) {
try {
for (let i = 0; i < funcs.length; i += 1) {
data = await funcs[i](data)
}
callback(undefined, data)
} catch (error) {
callback(error, undefined)}}}Copy the code
Implement Async Helper –parallel()
Bigfrontend. Dev/useful/problem /…
/* type Callback = (error: Error, data: any) => void type AsyncFunc = ( callback: Callback, data: any ) => void */
function promisify(func) {
return function (. args) {
return new Promise(function(resolve, reject) {
func(function (err, data) {
if (err) {
reject(err)
} else{ resolve(data) } }, ... args) }) } }/ * * *@param {AsyncFunc[]} funcs
* @return {(callback: Callback) => void}* /
function parallel(funcs){
funcs = funcs.map(func= > promisify(func))
return function (callback, data) {
let count = 0
let handleError = false
const result = []
for (let i = 0; i < funcs.length; i += 1) {
funcs[i](data).then(function (res) {
result[i] = res
count += 1
if (count === funcs.length) {
callback(undefined, result)
}
}).catch(function (err) {
if(! handleError) { callback(err,undefined)
handleError = true}})}}}Copy the code
Implement Async Helper –race()
Bigfrontend. Dev/useful/problem /…
/* type Callback = (error: Error, data: any) => void type AsyncFunc = ( callback: Callback, data: any ) => void */
function promisify(func) {
return function (. args) {
return new Promise(function(resolve, reject) {
func(function (err, data) {
if (err) {
reject(err)
} else{ resolve(data) } }, ... args) }) } }/ * * *@param {AsyncFunc[]} funcs
* @return {(callback: Callback) => void}* /
function race(funcs){
funcs = funcs.map(func= > promisify(func))
return function (callback, data) {
let handleEnd = false
for (let i = 0; i < funcs.length; i += 1) {
funcs[i](data).then(function (res) {
if(! handleEnd) { callback(undefined, res)
}
handleEnd = true
}).catch(function (err) {
if(! handleEnd) { callback(err,undefined)
}
handleEnd = true})}}}Copy the code
32. ImplementationPromise.all()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {Array<any>} promises - notice input might have non-Promises
* @return {Promise<any[]>}* /
function all(promises) {
return new Promise((resolve, reject) = > {
if(! promises.length) {return resolve([])
}
const result = [];
let count = 0;
for (let i = 0; i < promises.length; i++) {
const promise = promises[i] instanceof Promise ? promises[i] : Promise.resolve(promises[i])
promise.then((res) = > {
result[i] = res
count += 1
if (count === promises.length) {
resolve(result)
}
}).catch((err) = > {
reject(err)
})
}
})
}
Copy the code
33. ImplementationPromise.allSettled()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {Array<any>} promises - notice that input might contains non-promises
* @return {Promise<Array<{status: 'fulfilled', value: any} | {status: 'rejected', reason: any}>>}
*/
function allSettled(promises) {
return new Promise((resolve, reject) = > {
if(! promises.length) {return resolve([])
}
const result = [];
let count = 0;
for (let i = 0; i < promises.length; i++) {
const promise = promises[i] instanceof Promise ?
promises[i] :
Promise.resolve(promises[i])
promise.then((res) = > {
result[i] = {status:"fulfilled".value: res}
count += 1
if (count === promises.length) {
resolve(result)
}
}).catch((err) = > {
result[i] = {status:"rejected".reason: err}
count += 1
if (count === promises.length) {
resolve(result)
}
})
}
})
}
Copy the code
34. The implementationPromise.any()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {Array<Promise>} promises
* @return {Promise}* /
function any(promises) {
return new Promise((resolve, reject) = > {
if(! promises.length) {return reject(
new AggregateError(
'No Promise in Promise.any was resolved', []))}const errors = [];
let count = 0;
for (let i = 0; i < promises.length; i += 1) {
const promise = promises[i] instanceof Promise ? promises[i] : Promise.resolve(promises[i])
promise.then((res) = > {
resolve(res)
}).catch((err) = > {
errors[i] = err
count += 1
if (count === promises.length) {
reject(
new AggregateError(
'No Promise in Promise.any was resolved',
errors
)
)
}
})
}
})
}
Copy the code
35. The implementationPromise.race()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {Array<Promise>} promises
* @return {Promise}* /
function race(promises) {
return new Promise((resolve, reject) = > {
if (promises.length) {
for (let i = 0; i < promises.length; i += 1) {
const promise = promises[i] instanceof Promise ?
promises[i]
:
Promise.resolve(promises[i])
promise.then((res) = > {
resolve(res)
}).catch((err) = > {
reject(err)
})
}
}
})
}
Copy the code
37. Handwritten Binary Search (unique)
Bigfrontend. Dev/useful/problem /…
/ * * *@param {number[]} arr - ascending unique array
* @param {number} target
* @return {number}* /
function binarySearch(arr, target){
if (arr.length === 0) return -1
const _binarySearch = (arr, base) = > {
if (arr.length) {
const midd = Math.floor(arr.length / 2)
if (arr[midd] === target) {
return midd + base
} else if (arr[midd] > target) {
return _binarySearch(arr.splice(midd + 1), midd)
} else {
return _binarySearch(arr.splice(0, midd), base)
}
} else {
return -1}}return _binarySearch([...arr], 0)}Copy the code
38. The implementationjest.spyOn()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {object} obj
* @param {string} methodName* /
function spyOn(obj, methodName) {
if(! (obj[methodName]instanceof Function)) {
throw new Error()}const before = obj[methodName]
const calls = []
obj[methodName] = function (. args) {
calls.push([...args])
before.call(this. args) }return {
calls
}
}
Copy the code
39. The handwritten range ()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {integer} from
* @param {integer} to* /
function range(from, to) {
const result = []
while (from <= to) {
result.push(from)
from+ =1
}
return result
}
Copy the code
40. Handwritten bubble sort
Bigfrontend. Dev/useful/problem /…
Bubble sort, stable sort, O(n) space complexity, O(n^2) time complexity. Stable sorting means that the relative positions of elements do not change
/ * * *@param {number[]} arr* /
function bubbleSort(arr) {
for (let i = 0; i < arr.length; i += 1) {
for (let j = i + 1; j < arr.length; j += 1) {
if (arr[i] > arr[j]) {
[arr[i], arr[j]] = [arr[j], arr[i]]
}
}
}
return arr
}
Copy the code
41. Handwritten merge sort
Bigfrontend. Dev/useful/problem /…
Divide and conquer, merge sort is stable sort, order nlogn.
Reference article: stackabuse.com/merge-sort-…
// Note: Need to modify directly on the original array
function merge (left, right) {
const arr = []
while (left.length && right.length) {
if (left[0] > right[0]) {
arr.push(right.shift())
} else {
arr.push(left.shift())
}
}
return [...arr, ...left, ...right]
}
/ * * *@param {number[]} arr* /
function mergeSort(arr) {
if (arr.length <= 1) {
return arr
}
const midd = Math.floor(arr.length / 2)
const left = arr.splice(0, midd)
return merge(mergeSort(left), mergeSort(arr))
}
// Modify in place
// The outermost right of the recursion is the original array
function merge (left, right) {
const arr = []
while (left.length && right.length) {
if (left[0] > right[0]) {
arr.push(right.shift())
} else {
arr.push(left.shift())
}
}
while (arr.length) {
right.unshift(arr.pop())
}
if (left.length) {
right.push(left.pop())
}
return right
}
/ * * *@param {number[]} arr* /
function mergeSort(arr) {
if (arr.length <= 1) {
return arr
}
const midd = Math.floor(arr.length / 2)
const left = arr.splice(0, midd)
return merge(mergeSort(left), mergeSort(arr))
}
Copy the code
42. Handwritten insertion sort
Bigfrontend. Dev/useful/problem /…
Insert sort is stable sort, order n^2 in time.
/ * * *@param {number[]} arr* /
function insertionSort(arr) {
for (let i = 0; i < arr.length; i += 1) {
for (let j = i + 1; j < arr.length; j += 1) {
if (arr[i] > arr[j]) {
const item = arr.splice(j,1) [0]
arr.splice(i,0,item)
}
}
}
return arr
}
Copy the code
43. Handwritten quicksort
Bigfrontend. Dev/useful/problem /…
Quicksort is an unstable sort, with worst-case time order (n^2). The average time complexity is order nlogn.
// Note: Need to modify directly on the original array
/ * * *@param {number[]} arr* /
function quickSort(arr) {
if (arr.length <= 1) {
return arr
}
const referenceValue = arr[0]
const max = []
const min = []
for (let i = 1; i < arr.length; i += 1) {
if (arr[i] >= referenceValue) {
max.push(arr[i])
} else {
min.push(arr[i])
}
}
return quickSort(min).concat(referenceValue, quickSort(max))
}
// Modify in place
/ * * *@param {number[]} arr* /
function quickSort(arr) {
if (arr.length <= 1) {
return arr
}
const referenceValue = arr[0]
let max = []
let min = []
for (let i = 1; i < arr.length; i += 1) {
if(arr[i] >= referenceValue) { max.push(... arr.splice(i,1))}else{ min.push(... arr.splice(i,1))
}
i -= 1
}
min = quickSort(min)
max = quickSort(max)
while (max.length) {
arr.push(max.shift())
}
while (min.length) {
arr.unshift(min.pop())
}
return arr
}
Copy the code
44. Handwritten selection sort
Bigfrontend. Dev/useful/problem /…
www.geeksforgeeks.org/selection-s…
Selection sort is unstable sort, order n^2 time.
/ * * *@param {number[]} arr* /
function selectionSort(arr) {
for (let i = 0; i < arr.length; i += 1) {
let minIndex = i
for (let j = i + 1; j < arr.length; j += 1) {
if (arr[j] < arr[minIndex]) {
minIndex = j
}
}
const min = arr.splice(minIndex, 1) [0]
arr.splice(i, 0, min)
}
return arr
}
Copy the code
Find the KTH largest element in the unsorted array
Bigfrontend. Dev/useful/problem /…
/ / partition
/ * * *@param {number[]} arr
* @param {number} k* /
function findKThLargest(arr, k) {
let result
const divideAndConquer = (arr, base) = > {
if (arr.length <= 1) {
result = arr[0]}const min = []
const max = []
let maxLen
const referenceValue = arr[0]
for (let i = 1; i < arr.length; i += 1) {
if (arr[i] > referenceValue) {
max.push(arr[i])
} else {
min.push(arr[i])
}
}
max.push(arr[0])
maxLen = max.length + base
if (maxLen >= k && max.length) {
divideAndConquer(max, base)
} else if (maxLen < k && min.length) {
divideAndConquer(min, maxLen)
}
}
divideAndConquer(arr, 0)
return result
}
Copy the code
46. Achieve_.once()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {Function} func
* @return {Function}* /
function once(func) {
let result
let once = true
return function (. args) {
if (once) {
result = func.call(this. args) once =false
}
return result
}
}
Copy the code
Reverse linked lists
Bigfrontend. Dev/useful/problem /…
/** * class Node { * new(val: number, next: Node); * val: number * next: Node * } */
/ * * *@param {Node} list
* @return {Node} * /
const reverseLinkedList = (list) = > {
if(! list)return
const initNode = list
let newHead = initNode
let newHeadNextNode = initNode
while (initNode.next) {
newHead = initNode.next
if (newHead.next) {
initNode.next = newHead.next
} else {
initNode.next = null
}
newHead.next = newHeadNextNode
newHeadNextNode = newHead
}
return newHead
}
Copy the code
48. Returns the position of the first occurrence of a particular element in an array containing repeating elements
Bigfrontend. Dev/useful/problem /…
/ * * *@param {number[]} arr - ascending array with duplicates
* @param {number} target
* @return {number}* /
function firstIndex(arr, target){
if (arr.length === 0) return -1
let index = -1
const _firstIndex = (start, end) = > {
if (start <= end) {
const midd = Math.floor((start + end) / 2)
if (arr[midd] === target) {
if (index === -1) {
index = midd
} else {
index = Math.min(index, midd)
}
_firstIndex(start, midd - 1)}else if (arr[midd] > target) {
_firstIndex(start, midd - 1)}else {
_firstIndex(midd + 1, end)
}
}
}
_firstIndex(0, arr.length - 1)
return index
}
Copy the code
49. Returns the last occurrence of a particular element in an array containing repeating elements
Bigfrontend. Dev/useful/problem /…
/ * * *@param {number[]} arr - ascending array with duplicates
* @param {number} target
* @return {number}* /
function lastIndex(arr, target){
if (arr.length === 0) return -1
let index = -1
const _lastIndex = (start, end) = > {
if (start <= end) {
const midd = Math.floor((start + end) / 2)
if (arr[midd] === target) {
if (index === -1) {
index = midd
} else {
index = Math.max(index, midd)
}
_lastIndex(midd + 1, end)
} else if (arr[midd] > target) {
_lastIndex(start, midd - 1)}else {
_lastIndex(midd + 1, end)
}
}
}
_lastIndex(0, arr.length - 1)
return index
}
Copy the code
50. Returns the element before a particular element in an array with repeating elements
Bigfrontend. Dev/useful/problem /…
/ * * *@param {number[]} arr - ascending array with duplicates
* @param {number} target
* @return {number}* /
function firstIndex(arr, target){
if (arr.length === 0) return -1
let index = -1
const _firstIndex = (start, end) = > {
if (start <= end) {
const midd = Math.floor((start + end) / 2)
if (arr[midd] === target) {
if (index === -1) {
index = midd
} else {
index = Math.min(index, midd)
}
_firstIndex(start, midd - 1)}else if (arr[midd] > target) {
_firstIndex(start, midd - 1)}else {
_firstIndex(midd + 1, end)
}
}
}
_firstIndex(0, arr.length - 1)
return index
}
/ * * *@param {number[]} arr - ascending array with duplicates
* @param {number} target
* @return {number}* /
function elementBefore(arr, target){
if (arr.length === 0) return undefined
const _firstIndex = firstIndex(arr, target)
if (_firstIndex === 0 || _firstIndex === -1) return undefined
return arr[_firstIndex - 1]}Copy the code
51. The element that follows the specified element in an array containing repeating elements
Bigfrontend. Dev/useful/problem /…
/ * * *@param {number[]} arr - ascending array with duplicates
* @param {number} target
* @return {number}* /
function lastIndex(arr, target){
if (arr.length === 0) return -1
let index = -1
const _lastIndex = (start, end) = > {
if (start <= end) {
const midd = Math.floor((start + end) / 2)
if (arr[midd] === target) {
if (index === -1) {
index = midd
} else {
index = Math.max(index, midd)
}
_lastIndex(midd + 1, end)
} else if (arr[midd] > target) {
_lastIndex(start, midd - 1)}else {
_lastIndex(midd + 1, end)
}
}
}
_lastIndex(0, arr.length - 1)
return index
}
/ * * *@param {number[]} arr - ascending array with duplicates
* @param {number} target
* @return {number}* /
function elementAfter(arr, target){
if (arr.length === 0) return undefined
const _lastIndex = lastIndex(arr, target)
if (_lastIndex === arr.length - 1 || _lastIndex === -1) return undefined
return arr[_lastIndex + 1]}Copy the code
53. The realization of middleware
Bigfrontend. Dev/useful/problem /…
class Middleware {
constructor () {
this.callbacks = []
this.handleErrors = []
this.handleNextError = null
}
// The onion model
_compose(funcs, type) {
if (funcs.length === 0) {
return arg= > arg
}
if (funcs.length === 1) {
return funcs[0]}if (type= = ='callback') {
return funcs.reduce((a, b) = > {
return (req, next) = > {
return a(req, (err) = > {
if (err) {
this.handleNextError(err)
} else {
b(req, next)
}
})
}
})
} else if (type= = ='handleError') {
return funcs.reduce((a, b) = > {
return (err, req, next) = > {
return a(err, req, (err) = > {
b(err, req, next)
})
}
})
}
}
/ * * *@param {MiddlewareFunc} func* /
use(func) {
if (func.length === 2) {
this.callbacks.push(func)
} else {
this.handleErrors.push(func)
}
}
/ * * *@param {Request} req* /
start(req) {
const callback = this._compose(this.callbacks, 'callback')
const handleError = this._compose(this.handleErrors, 'handleError')
this.handleNextError = (err) = > {
handleError(err, req, () = >{})}try {
callback(req, (err) = > {
if (err) {
this.handleNextError(err)
}
})
} catch (err) {
handleError(err, req, () = >{})}}}Copy the code
const middleware = new Middleware()
middleware.use((req, next) = > {
console.log(1)
next()
console.log(2)})// since error occurs, this is skipped
middleware.use((req, next) = > {
console.log(3)
next(new Error())
console.log(4)})// since error occurs, this is called
middleware.use((error, req, next) = > {
console.log(error)
console.log(req)
})
middleware.start({})
Copy the code
class Middleware {
constructor () {
this.callbacks = []
this.handleErrors = []
}
/ * * *@param {MiddlewareFunc} func* /
use(func) {
if (func.length === 2) {
this.callbacks.push(func)
} else {
this.handleErrors.push(func)
}
}
/ * * *@param {Request} req* /
start(req) {
let callbackIndex = 0
let handleErrorIndex = 0
const next = (error) = > {
const args = [req, next]
let func
if (error) {
func = this.handleErrors[handleErrorIndex]
args.unshift(error)
handleErrorIndex += 1
} else {
func = this.callbacks[callbackIndex]
callbackIndex += 1
}
try{ func && func(... args) }catch (err) {
next(err)
}
}
next()
}
}
Copy the code
🐜 Ant Financial service: compose implementation
function f(next) {console.log(1); next();console.log(2); }function g(next) {console.log(3); next();console.log(4); }function h(next) {console.log(5); next();console.log(6); }// ((next) => {
// ((next) => {
// return f(() => {
// g(next)
/ /})
// })(() => { h(next) })
/ / (() = > {})
// console.log('ok')
// })
// The final goal that needs to be achieved
// f(() => {
// g(() => {
// h(() => {
/ /})
/ /})
// })
/ / implementation compose
function compose(. funcs) {
r
return function () {
return funcs.reduce((a,b) = > {
return (next) = > {
return a(() = > {
b(next)
})
}
})(() = >{})}}/ / 1,3,5,6,4,2
// Next => f(() => g(next))
// a: (next) => f(() => g(next)) b: h
/ / the second return (next) = > ((next) = > f (() = > g (next)) (() = > h (next))
// (next) =>f(() => g(() => h(next)))
compose(f,g,h)()
Copy the code
53. Implemented with ES5extends
Bigfrontend. Dev/useful/problem /…
const myExtends = (SuperType, SubType) = > {
function Child (. args) {
SuperType.call(this. args) SubType.call(this. args)// Child is a SubType
Object.setPrototypeOf(this, SubType.prototype)
}
SubType.prototype = Object.create(SuperType.prototype)
Child.prototype = Object.create(SubType.prototype)
SubType.prototype.constructor = SubType
Child.prototype.constructor = Child
// Emulate the additional inheritance chain of ES6
Object.setPrototypeOf(Child, SuperType)
return Child
}
Copy the code
55. Highlight keywords in the HTML string
Bigfrontend. Dev/useful/problem /…
// Get permutations of all keywords
/ * * *@param {string} html
* @param {string[]} keywords* /
function highlightKeywords(html, keywords) {
const combination = []
let arr = html.split(' ')
const getCombination = (head, arr) = > {
for (let i = 0; i < arr.length; i += 1) {
const temp = [...arr]
temp.splice(i, 1)
const name = `${head}${arr[i]}`
combination.push(name)
getCombination(name, temp)
}
}
getCombination(' ', keywords)
arr = arr.map((item) = > {
if (combination.includes(item)) {
return `<em>${item}</em>`
} else if (keywords.some((keyword) = > item.includes(keyword))) {
for (let i = 0; i < keywords.length; i += 1) {
const keyword = keywords[i]
if (item.includes(keyword)) {
const reg = new RegExp(keyword, 'g')
item = item.replace(reg, `<em>${keyword}</em>`)
break}}return item
} else {
return item
}
})
return arr.join(' ')};// Simply use the re
Copy the code
58. Return the height of the DOM tree
Bigfrontend. Dev/useful/problem /…
/ * * *@param {HTMLElement | null} tree
* @return {number}* /
function getHeight(tree) {
if(! tree)return 0
const result = []
const bfs = (nodes) = > {
if (nodes.length) {
let childs = []
for (let i = 0; i < nodes.length; i += 1) {
const children = nodes[i].children
childs = [...childs, ...children]
}
result.push(childs)
bfs(childs)
}
}
bfs([tree])
return result.length
}
Copy the code
59. Implement Browser History
Bigfrontend. Dev/useful/problem /…
class BrowserHistory {
constructor(url) {
this.history = [url || undefined]
this.index = 0
}
visit(url) {
if (this.index === this.history.length - 1) {
this.history.push(url)
} else {
this.history = this.history.splice(0.this.index + 1)
this.history.push(url)
}
this.index = this.history.length - 1
}
get current() {
return this.history[this.index]
}
goBack() {
this.index -= 1
this.index = this.index < 0 ? 0 : this.index
return this.history[this.index]
}
forward() {
this.index += 1
this.index = this.index > this.history.length - 1 ? this.history.length - 1 : this.index
return this.history[this.index]
}
}
Copy the code
60. Make yoursnew
Bigfrontend. Dev/useful/problem /…
/ * * *@param {Function} constructor
* @param {any[]} args- argument passed to the constructor * `myNew(constructor, ... args)` should return the same as `new constructor(... args)` */
const myNew = (constructor, ... args) = > {
const obj = Object.create({})
const returnValue = constructor.call(obj, ... args)
Object.setPrototypeOf(obj, constructor.prototype)
return returnValue || obj
}
Copy the code
61.Function.prototype.call
Bigfrontend. Dev/useful/problem /…
Function.prototype.mycall = function(thisArg, ... args) {
if (thisArg === undefined || thisArg === null) {
thisArg = window
}
if (typeof thisArg === 'string') {
thisArg = new String(thisArg)
}
if (typeof thisArg === 'number') {
thisArg = new Number(thisArg)
}
if (typeof thisArg === 'boolean') {
thisArg = new Boolean(thisArg)
}
const key = Symbol()
thisArg[key] = this
constresult = thisArg[key](... args)delete thisArg[key]
return result
}
Copy the code
Handwritten apply
Function.prototype.myapply = function (thisArg, argsArray = []) {
if (!Array.isArray(argsArray)) {
throw new Error()}if (thisArg === undefined || thisArg === null) {
thisArg = window
}
if (typeof thisArg === 'string') {
thisArg = new String(thisArg)
}
if (typeof thisArg === 'number') {
thisArg = new Number(thisArg)
}
if (typeof thisArg === 'boolean') {
thisArg = new Boolean(thisArg)
}
const key = Symbol()
thisArg[key] = this
constresult = thisArg[key](... argsArray)delete thisArg[key]
return result
}
Copy the code
Write a bind
Function.prototype.mybind = function (thisArg, ... initArgs) {
if (thisArg === undefined || thisArg === null) {
thisArg = window
}
if (typeof thisArg === 'string') {
thisArg = new String(thisArg)
}
if (typeof thisArg === 'number') {
thisArg = new Number(thisArg)
}
if (typeof thisArg === 'boolean') {
thisArg = new Boolean(thisArg)
}
const that = this
return function (. args) {
const key = Symbol()
thisArg[key] = that
constresult = thisArg[key](... initArgs, ... args)delete thisArg[key]
return result
}
}
Copy the code
63. The handwritten_.cloneDeep()
Bigfrontend. Dev/useful/problem /…
// Avoid circular references
const hash = new WeakMap(a)function isObject(value) {
returnvalue ! =null && (typeof value === "object" || typeof value === "function")}function getSymbolKeys(value) {
let keys = Object.getOwnPropertySymbols(value)
keys = keys.filter((key) = > value.propertyIsEnumerable(key))
return keys
}
function getAllKeys(value) {
let keys = Object.keys(value)
keys = [...keys, ...getSymbolKeys(value)]
return keys
}
function cloneDeep(data) {
let result = null
if(! isObject(data)) {return data
}
const isArray = Array.isArray(data)
if (isArray) {
result = []
} else {
result = Object.create(Object.getPrototypeOf(data))
}
if (hash.has(data)) {
return hash.get(data)
} else {
hash.set(data, result)
}
const keys = getAllKeys(data)
for (let i = 0; i < keys.length; i += 1) {
const key = keys[i]
const val = data[key]
result[key] = cloneDeep(val)
}
return result
}
Copy the code
64. Automatically retry Promise Reject
Bigfrontend. Dev/useful/problem /…
/ * * *@param {() => Promise<any>} fetcher
* @param {number} maximumRetryCount
* @return {Promise<any>}* /
function fetchWithAutoRetry(fetcher, maximumRetryCount) {
return new Promise(async (resolve, reject) => {
let error
for (let i = 0; i <= maximumRetryCount; i += 1) {
await fetcher().then((res) = > {
resolve(res)
}).catch((err) = > {
error = err
})
}
reject(error)
})
}
Copy the code
65. Add thousands separator
Bigfrontend. Dev/useful/problem /…
/ * * *@param {number} num
* @return {string}* /
function addComma(num) {
num = `${num}`
const reg = /\B(? =(\d{3})+$)/g
const decimalPlaces = num.split('. ') [1]
let integerBits = num.split('. ') [0]
integerBits = integerBits.replace(reg, ', ')
if (decimalPlaces) {
return `${integerBits}.${decimalPlaces}`
}
return `${integerBits}`
}
Copy the code
66. Remove duplicate elements from an array
Bigfrontend. Dev/useful/problem /…
/ * * *@param {any[]} arr* /
function deduplicate(arr) {
const map = new Map(a)for (let i = 0; i < arr.length; i += 1) {
if (map.has(arr[i])) {
arr.splice(i, 1)
i -= 1
} else {
map.set(arr[i], true)}}return arr
}
Copy the code
69._.isEqual()
Bigfrontend. Dev/useful/problem /…
const getSymbolKeys = (obj) = > {
let symbolKeys = Object.getOwnPropertySymbols(obj)
symbolKeys = [...symbolKeys].filter((key) = > {
return obj.propertyIsEnumerable(key)
})
return symbolKeys
}
const getAllKeys = (obj) = > {
let keys = Object.keys(obj)
keys = [...keys, ...getSymbolKeys(obj)]
return keys
}
function isObject(value) {
returnvalue ! =null && (typeof value === "object" || typeof value === "function")}const hash = new WeakMap(a)/ * * *@param {any} a
* @param {any} b
* @return {boolean}* /
function isEqual(a, b) {
let result = true
const equal = (a, b) = > {
if(! isObject(a) || ! isObject(b)) { result = (a === b)return
}
if (hash.has(a) && hash.has(b)) {
return true
}
const aKeys = getAllKeys(a)
const bKeys = getAllKeys(b)
if(aKeys.length ! == bKeys.length) { result =false
return
}
hash.set(a, true)
hash.set(b, true)
for (let i = 0; i < aKeys.length; i += 1) {
const key = aKeys[i]
const aValue = a[key]
const bValue = b[key]
if(! isObject(aValue) || ! isObject(bValue)) {if(aValue ! == bValue) { result =false
break}}else {
isEqual(aValue, bValue)
}
}
}
equal(a, b)
return result
}
Copy the code
79. Convert snake_case to camelCase
Bigfrontend. Dev/useful/problem /…
/ * * *@param {string} str
* @return {string}* /
function snakeToCamel(str) {
const reg = /([^_])_([^_])/g
return str.replaceAll(reg, (_, p1, p2) = > `${p1}${p2.toUpperCase()}`)}Copy the code
CamelCase is converted to snake_case
Not tested for boundary cases
/* * @param {string} str * @return {string} */
function camelToSnake(str) {
const reg = /\B(\w)([A-Z])\B/g
return str.replaceAll(reg, (_, p1, p2) = > `${p1}_${p2.toLowerCase()}`)}Copy the code
Merge sorted arrays
Bigfrontend. Dev/useful/problem /…
/ * * *@param {number[][]} arrList
* non-descending integer array
* @return {number[]} * /
function merge(arrList) {
let result = []
let offset = false
const isMerge = () = > {
let count = 0
for (let i = 0; i < arrList.length; i += 1) {
if (arrList[i].length > 0) count += 1
if (count >= 2) break
}
return count >= 2 ? true : false
}
offset = isMerge()
while (offset) {
let index = 0
let min = Number.MAX_VALUE
for (let i = 0; i < arrList.length; i += 1) {
if (arrList[i][0] <= min) {
index = i
min = arrList[i][0] } } result.push(... arrList[index].splice(0.1))
offset = isMerge()
}
for (let i = 0; i < arrList.length; i += 1) {
result = [...result, ...arrList[i]]
}
return result
}
Copy the code
85._.get()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {object} source
* @param {string | string[]} path
* @param {any} [defaultValue]
* @return {any}* /
function get(source, path, defaultValue = undefined) {
if (typeof path === 'string') {
path = path.split('. ')}const newPath = []
const reg = /^([A-Za-z]+)\[([0-9]+)]$/g
let result = source
for (let i = 0; i < path.length; i += 1) {
if (path[i].includes('[')) {
const arr = reg.exec(path[i])
newPath.push(arr[1])
newPath.push(arr[2])}else {
newPath.push(path[i])
}
}
for (let i = 0; i < newPath.length; i += 1) {
if (result === undefined || result === null) {
result = defaultValue
break
}
result = result[newPath[i]]
}
console.log(result)
return result ? result : defaultValue
}
Copy the code
87. Return the longest non-repeating substring
Bigfrontend. Dev/useful/problem /…
Use double Pointers and hashes
/ * * *@param {string} str
* @return {string}* /
function longestUniqueSubstr(str) {
const hash = {}
let result = ' '
let current = ' '
let start = 0
let end = 0
while (start <= end && end <= str.length - 1) {
if (hash[str[end]] === undefined) {
hash[str[end]] = end
} else {
start = hash[str[end]] + 1
hash[str[end]] = end
Object.keys(hash).forEach((key) = > {
if (hash[key] < start) delete hash[key]
})
}
current = str.slice(start, end + 1)
if (result.length < current.length) {
result = current
}
end += 1
}
return result
}
Copy the code
89. Return the “right” element in the DOM Tree
Bigfrontend. Dev/useful/problem /…
/ * * *@param {HTMLElement} root
* @param {HTMLElement} target
* @return {HTMLElemnt | null}* /
function nextRightSibling(root, target) {
if(! root)return null
let result = null
const bfs = (nodes) = > {
if (nodes.length) {
let childs = []
for (let i = 0; i < nodes.length; i += 1) {
const children = nodes[i].children
childs = [...childs, ...children]
}
for (let i = 0; i < childs.length; i += 1) {
if (childs[i] === target) {
if (i === childs.length - 1) {
result = null
return
} else {
result = childs[i + 1]
return
}
}
}
bfs(childs)
}
}
bfs([root])
return result
}
Copy the code
90.instanceof
Bigfrontend. Dev/useful/problem /…
/ * * *@param {any} obj
* @param {target} target
* @return {boolean}* /
function myInstanceOf(obj, target) {
if (typeofobj ! = ='object' || obj === null) {
return false
}
const proto = Object.getPrototypeOf(obj)
if (proto === null) {
return false
}
if (proto === target.prototype) {
return true
} else {
return myInstanceOf(proto, target)
}
}
Copy the code
Reverse binary tree
Bigfrontend. Dev/useful/problem /…
/ * * *@param {Node} node
* @returns {Node}* /
function invert(node) {
if(! node)return null
const traverside = (node) = > {
if (node) {
const left = node.left
const right = node.right
node.right = left
node.left = right
traverside(left)
traverside(right)
}
}
traverside(node)
return node
}
Copy the code
92. Promise throttling
Bigfrontend. Dev/useful/problem /…
/ * * *@param {() => Promise<any>} func
* @param {number} max
* @return {Promise}* /
function throttlePromises(funcs, max){
return new Promise(function (resolve, reject) {
const result = []
const len = funcs.length
let jobs = 0
let count = 0
const handleJobs = () = > {
while (jobs < max && funcs.length) {
let promise = funcs.shift()()
let index = len - funcs.length - 1
promise = promise instanceof Promise ? promise : Promise.resolve(promise)
promise.then((res) = > {
result[index] = res
count += 1
jobs -= 1
if (count === len) {
resolve(result)
}
handleJobs()
}).catch((err) = > {
reject(err)
})
jobs += 1
}
}
handleJobs()
})
}
Copy the code
94.Object.create
Bigfrontend. Dev/useful/problem /…
/ * * *@param {any} proto
* @return {object}* /
function myObjectCreate(proto) {
if(! (protoinstanceof Object)) {
throw new Error()}const obj = {}
obj.__proto__ = proto
return obj
}
/ * * *@param {any} proto
* @return {object}* /
function myObjectCreate(proto) {
if(! (protoinstanceof Object)) {
throw new Error()}function Constructor () {}
Constructor.prototype = proto
return new Constructor();
}
// Error
// ES6's class syntax cannot modify class constructor.prototype
// https://stackoverflow.com/questions/37680766/how-to-change-classs-prototype-in-es6
/ * * *@param {any} proto
* @return {object}* /
function myObjectCreate(proto) {
if(! (protoinstanceof Object)) {
throw new Error()}class Constructor {}
Constructor.prototype = proto
return new Constructor();
}
Copy the code
95. The realization of String. The prototype. The trim ()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {string} str
* @return {string}* /
function trim(str) {
return str.replace(/^\s+|\s+$/g.' ')}Copy the code
97. Compress strings
Bigfrontend. Dev/useful/problem /…
/ * * *@param {string} str
* @return {string}* /
function compress(str) {
let s = str[0]
let p = str[0]
let n = 1
for (let i = 1; i < str.length; i += 1) {
if (str[i] === p) {
n += 1
if (n > 2) {
let arr = s.split(' ')
arr.pop()
s = `${arr.join(' ')}${n}`
} else {
s = `${s}${n}`}}else {
p = str[i]
n = 1
s = `${s}${str[i]}`}}return s
}
Copy the code
99. Extract all in the HTML string<a/>
Bigfrontend. Dev/useful/problem /…
/ * * *@param {string} str
* @return {string[]}* /
function extract(str) {
const result = []
// (\s[^>]*)? , if there is [^>], there must be a space
// [^>] also includes Spaces
const reg = /
]*)? >. *? <\s*\/\s*a>/g
(\s[^>
let controller = true
while (controller) {
const match = reg.exec(str)
if (match) {
result.push(match[0])}else {
controller = false}}return result
}
Copy the code
100. Check if there are rings in the linked list
Bigfrontend. Dev/useful/problem /…
/ * * *@param {Node} head
* @return {boolean}* /
function hasCircle(head) {
let fast = head
let slow = head
let offset = true
let result = false
while(offset && fast && slow) { fast = fast? .next slow = slow? .next? .nextif (fast === slow) {
result = true
offset = false}}return result
}
Copy the code
102. Validate parenthesis strings
Bigfrontend. Dev/useful/problem /…
class Stack {
constructor () {
this.stack = []
Object.defineProperties(this, {
size: {
set () {
throw new Error()
},
get () {
return this.stack.length
}
}
})
}
push (n) {
this.stack.push(n)
}
pop () {
return this.stack.pop()
}
peek () {
return this.stack[this.stack.length - 1]}}/ * * *@param {string} str
* @return {boolean} * /
function validate(str) {
const stack = new Stack()
for (let i = 0; i < str.length; i += 1) {
if (stack.size === 0) {
stack.push(str[i])
} else {
const top = stack.peek()
if (top === '[' && str[i] === '] ') {
stack.pop()
continue
} else if (top === '{' && str[i] === '} ') {
stack.pop()
continue
} else if (top === '(' && str[i] === ') ') {
stack.pop()
continue
} else {
stack.push(str[i])
}
}
}
return stack.size === 0 ? true : false
}
Copy the code
103. The realization of Math. SQRT ()
Bigfrontend. Dev/useful/problem /…
Use dichotomy
/ * * *@param {any} x
* @return {number}* /
function mySqrt(x) {
if(! (typeof x === "number"&&!isNaN(x) && x >= 0)) return NaN
if (x === 0) return 0
if (x === 1) return 1
let result = null
const sqrt = (start, end) = > {
if (start <= end) {
const midd = Math.floor((end + start) / 2)
if (midd ** 2 < x) {
result = midd
sqrt(midd + 1, end)
} else if (midd ** 2 > x) {
sqrt(start, midd - 1)}else {
result = midd
}
}
}
sqrt(0, x)
return result
}
Copy the code
104. Traverse the DOM tree layer by layer
Bigfrontend. Dev/useful/problem /…
/ * * *@param {HTMLElement | null} root
* @return {HTMLElement[]}* /
// bfs
function flatten(root) {
if(! root)return []
const result = [root]
const bfs = (nodes) = > {
if (nodes.length) {
const children = []
for (let i = 0; i < nodes.length; i += 1) {
constchild = nodes[i].children children.push(... child) } result.push(... children) bfs(children) } } bfs([root])return result
}
Copy the code
105. Find the first repeated character
Bigfrontend. Dev/useful/problem /…
Using the hash
/ * * *@param {string} str
* @return {string | null}* /
function firstDuplicate(str) {
let result = null
const hash = {}
for (let i = 0; i < str.length; i += 1) {
const key = str[i]
if(! hash[key]) { hash[key] =true
} else {
result = key
break}}return result
}
Copy the code
Find two numbers that add up to 0
Bigfrontend. Dev/useful/problem /…
Using the hash method
/ * * *@param {number[]} arr
* @return {number[]}* /
function findTwo(arr) {
const hash = {}
let result = null
for (let i = 0; i < arr.length; i += 1) {
if(! hash[arr[i]]) hash[arr[i]] = [i]else hash[arr[i]].push(i)
}
for (let i = 0; i < arr.length; i += 1) {
const a = arr[i]
const index = hash[a].shift()
const b = 0 - a
if (hash[b] && hash[b].length > 0) {
result = [index, hash[b][0]]
break
} else {
hash[a].unshift(index)
}
}
return result
}
Copy the code
107. Find the biggest difference
Bigfrontend. Dev/useful/problem /…
/ * * *@param {number[]} arr
* @return {number}* /
function largestDiff(arr) {
if (arr.length === 0) return 0
if (arr.length === 1) return 0
let min = Infinity
let max = -Infinity
for (let i = 0; i < arr.length; i += 1) {
min = Math.min(arr[i], min)
max = Math.max(arr[i], max)
}
return Math.abs(min - max)
}
Copy the code
108. Implementing a Stack with a Queue
Bigfrontend. Dev/useful/problem /…
Similar to problem 13
/* you can use this Queue which is bundled together with your code class Queue { enqueue(element) { // add new element to the queue } peek() { // return the head element } dequeue() { // remove head element from the queue } size() { // return the queue size } } */
// you need to complete the following Stack, using only Queue
class Stack {
constructor () {
this.queue = new Queue()
this.stack = new Queue()
}
push(element) {
while (this.stack.size()) {
this.queue.enqueue(this.stack.dequeue())
}
this.stack.enqueue(element)
while (this.queue.size()) {
this.stack.enqueue(this.queue.dequeue())
}
}
peek() {
return this.stack.peek()
}
pop() {
return this.stack.dequeue()
}
size() {
return this.stack.size()
}
}
Copy the code
109.Math.pow()
Bigfrontend. Dev/useful/problem /…
Divide and conquer, reduce the number of times
/ * * *@param {number} base
* @param {number} power - integer
* @return {number}* /
function pow(base, power){
const isNegativeIndex = power < 0
const isNegative = base < 0
const _pow = (base, power) = > {
if (power === 0) return 1
if (power === 1) return base
let result = power % 2= = =0 ?
pow(base * base, power / 2)
:
pow(base * base, (power - 1) / 2) * base
return result
}
let result = _pow(Math.abs(base), Math.abs(power))
result = isNegativeIndex ? 1 / result : result
result = isNegative ? result * -1 : result
return result
}
Copy the code
116. The achieve Object. Is ()
Bigfrontend. Dev/useful/problem /…
Medium.com/coding-at-d…
/ * * *@param {any} a
* @param {any} b
* @return {boolean}* /
function is(a, b) {
if (typeof a === 'number' && typeof b === 'number') {
if (isNaN(a) && isNaN(b)) {
return true
} else if (a === 0 && b === 0) {
return 1/a === 1/b
}
}
return a === b
}
Copy the code
Create a Tokenizer
Bigfrontend. Dev/useful/problem /…
/ * * *@param {string} str
* @return {Generator}* /
function* tokenize(str) {
let temp = str.replace(/\s/g.' ')
let num = ' '
for (let i = 0; i < temp.length; i += 1) {
const s = temp[i]
switch (s) {
case '+':
case The '-':
case The '*':
case '/':
case '(':
case ') ':
if(num ! = =' ') {
yield num
num = ' '
}
yield s
break
default:
num += s
break}}if(num ! = =' ') {
yield num
}
}
Copy the code
122. Realize memoizeOne ()
Bigfrontend. Dev/useful/problem /…
const compare = (oldKey, newKey) = > {
if (Array.isArray(oldKey) && Array.isArray(newKey) && oldKey.length === newKey.length) {
return oldKey.every((key, i) = > key === newKey[i])
}
return oldKey === newKey
}
/ * * *@param {Function} func
* @param {(args: any[], newArgs: any[]) => boolean} [isEqual]
* @returns {any}* /
function memoizeOne(func, isEqual = compare) {
let oldKey = Symbol(a)let catchResult = null
let that = null
let isCall = false
return function (. params) {
if(that ! = =this) {
oldKey = Symbol()
that = this
}
if (isCall && isEqual(oldKey, [...params])) {
return catchResult
}
isCall = true
oldKey = [...params]
const result = func.apply(this, [...params])
catchResult = result
return result
}
}
Copy the code
123. The implementation Promise. Prototype. Finally ()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {Promise<any>} promise
* @param {() => void} onFinally
* @returns {Promise<any>}* /
function myFinally(promise, onFinally) {
return promise.then((res) = > {
return Promise.resolve(onFinally()).then(() = > {
return res
})
}).catch((err) = > {
return Promise.resolve(onFinally()).then(() = > {
throw err
})
})
}
Copy the code
125. Realize classNames ()
Bigfrontend. Dev/useful/problem /…
function getKeys (obj) {
return [...Object.keys(obj)]
}
function getType (data) {
const type = Object.prototype.toString.call(data);
return /^\[object\s+([A-Za-z]+)\]$/.exec(type) [1].toLocaleLowerCase()
}
function trim(str) {
return str.replace(/^\s+|\s+$/g.' ')}function isNumberTypeOrStringNumber (data) {
const type = getType(data)
if (type= = ='number' || type= = ='string') {
return true
}
return false
}
/ * * *@param {any[]} args
* @returns {string}* /
function classNames(. args) {
let result = ' '
const _classNames = (value) = > {
const type = getType(value)
if (type= = ='number') {
result += ` ${value}`
return
}
if (type= = ='string') {
result += ` ${value}`
return
}
if (type= = ='map' || type= = ='object') {
const keys = getKeys(value)
for (let i = 0; i < keys.length; i += 1) {
const key = keys[i]
const val = value[key]
if (val) {
if (isNumberTypeOrStringNumber(key)) {
result += ` ${key}`
} else {
_classNames(val)
}
}
}
return
}
if (type= = ='set' || type= = ='array') {
value.forEach((val) = > {
if (val) {
if (isNumberTypeOrStringNumber(val)) {
result += ` ${val}`
} else {
_classNames(val)
}
}
})
}
}
for (let i = 0; i < args.length; i += 1) {
_classNames(args[i])
}
return trim(result)
}
Copy the code
130. Create LazyMan ()
Bigfrontend. Dev/useful/problem /…
// interface Laziness {
// sleep: (time: number) => Laziness
// sleepFirst: (time: number) => Laziness
// eat: (food: string) => Laziness
// }
function sleep (time) {
return new Promise(function (resolve) {
setTimeout(() = > {
resolve()
}, time)
})
}
/ * * *@param {string} name
* @param {(log: string) => void} logFn
* @returns {Laziness}* /
function LazyMan(name, logFn) {
const queue = [() = > {
logFn(`Hi, I'm ${name}. `)}]let update = false
const handleQueue = function () {
update = true
if (update) {
Promise.resolve().then(async function () {
update = false
for (let i = 0; i < queue.length; i += 1) {
await queue[i]()
}
})
}
}
const laziness = {
sleep (time) {
queue.push(async() = > {await sleep(time * 1000)
logFn(time > 1 ? `Wake up after ${time} seconds.` : `Wake up after ${time} second.`)})if(! update) { handleQueue() }return laziness
},
sleepFirst (time) {
queue.unshift(async() = > {await sleep(time * 1000)
logFn(time > 1 ? `Wake up after ${time} seconds.` : `Wake up after ${time} second.`)})if(! update) { handleQueue() }return laziness
},
eat (food) {
queue.push(() = > {
logFn(`Eat ${food}. `)})if(! update) { handleQueue() }return laziness
}
}
if(! update) { handleQueue() }return laziness
}
Copy the code
131. _. The chunk ()
Bigfrontend. Dev/useful/problem /…
/ * * *@param {any[]} items
* @param {number} size
* @returns {any[][]}* /
function chunk(items, size) {
if (size === 0 || items.length === 0) {
return[]}const result = []
while (items.length) {
result.push(items.splice(0, size))
}
return result
}
Copy the code
137. Vertical traversal of binary trees
Bigfrontend. Dev/useful/problem /…
/ * * *@param {Node} root
* @returns {number[]}* /
function traverse(root) {
let result = []
const hash = {}
const helper = (node, offset, fnode, depth) = > {
if (node) {
result.push({
value: node.value,
offset,
fnode,
depth
})
helper(node.left, offset - 1, node, depth + 1)
helper(node.right, offset + 1, node, depth + 1)
}
}
helper(root, 0.null.0)
result.sort((a,b) = > {
if(a.offset ! == b.offset) {return a.offset - b.offset
} else if(a.depth ! == b.depth) {return a.depth - b.depth
} else {
return 0}})// Build a hash to find the parent index
result.forEach((item, i) = >{ hash[item.value] = { ... item, i, } })console.log(hash)
console.log(result)
result.sort((a,b) = > {
if(a.offset ! == b.offset) {return a.offset - b.offset
} else if(a.depth ! == b.depth) {return a.depth - b.depth
} else {
// Root node special processing
if(! a.fnode) {return -1
} else if(! b.fnode) {return 1
} else {
const aFnodeIndex = hash[a.fnode.value].i
const bFnodeIndex = hash[b.fnode.value].i
return aFnodeIndex - bFnodeIndex
}
}
})
return result.map(item= > item.value)
}
Copy the code
138. Intersection of sorted arrays
Bigfrontend. Dev/useful/problem /…
Hash methods:
/ * * *@param {number[]} arr1 - integers
* @param {number[]} arr2 - integers
* @returns {number[]}* /
function intersect(arr1, arr2) {
const hash = {}
const result = []
for (let i = 0; i < arr1.length; i += 1) {
const key = arr1[i]
if(! hash[key]) { hash[key] =1
} else {
hash[key] += 1}}for (let i = 0; i < arr2.length; i += 1) {
const key = arr2[i]
if (hash[key]) {
hash[key] -= 1
result.push(key)
}
}
return result
}
Copy the code
Using double Pointers:
/ * * *@param {number[]} arr1 - integers
* @param {number[]} arr2 - integers
* @returns {number[]}* /
function intersect(arr1, arr2) {
const result = []
let pointer1 = 0
let pointer2 = 0
while (pointer1 < arr1.length && pointer2 < arr2.length) {
if (arr1[pointer1] === arr2[pointer2]) {
result.push(arr1[pointer1])
pointer1 += 1
pointer2 += 1
} else if (arr1[pointer1] > arr2[pointer2]) {
pointer2 += 1
} else if (arr1[pointer1] < arr2[pointer2]) {
pointer1 += 1}}return result
}
Copy the code
139. 实现_.partial()
Bigfrontend. Dev/useful/problem /…
function merge(params1, params2) {
for (let i = 0; i < params1.length; i += 1) {
if (params2.length) {
if (typeof params1[i] === 'symbol') {
const first = params2.shift()
params1[i] = first
}
} else {
break}}return [...params1, ...params2]
}
/ * * *@param {Function} func
* @param {any[]} args
* @returns {Function}* /
function partial(func, ... initArgs) {
return function (. args) {
let params = merge([...initArgs], [...args])
params = params.map((arg) = > {
if (typeof arg === 'symbol') {
return undefined
} else {
return arg
}
})
return func.call(this. params) } } partial.placeholder =Symbol(a)Copy the code
145. Most recurring characters
Bigfrontend. Dev/useful/problem /…
function count(str: string) :string | string[] {
const map = {}
let result = []
for (let i = 0; i < str.length; i += 1) {
if(! map[str[i]]) { map[str[i]] =1
} else {
map[str[i]] += 1}}const max = Math.max(... Object.values(map))for (let key in map) {
if (map[key] === max) {
result.push(key)
}
}
return result.length > 1 ? result : result[0]}Copy the code
146. The realization of an Array. The prototype. The reduce ()
Bigfrontend. Dev/useful/problem /…
Array.prototype.myReduce = function (callback, initialValue) {
const argsLength = arguments.length
if (argsLength === 1 && this.length === 0) {
throw new Error()}let index = argsLength === 1 ? 1 : 0
let resultValue = argsLength === 1 ? this[0] : initialValue
for (let i = index; i < this.length; i += 1) {
resultValue = callback(resultValue, this[i], i, this)}return resultValue
}
Copy the code
147. Stone
Bigfrontend. Dev/useful/problem /…
I didn’t think this problem through very well
function canWinStonePicking(n) {
if (n === 0) return null
if (n === 1) return 'B'
if (n === 2) return 'A'
const firstMove = new Map([[1.false],
[2.true]])const backhand = new Map([[1.true],
[2.false]])for (let i = 3; i <= n; i += 1) {
firstMove.set(i, (backhand.get(i-2) || backhand.get(i-1)))
backhand.set(i, (firstMove.get(i-2) && firstMove.get(i-1)))}return firstMove.get(n) ? 'A' : backhand.get(n) ? 'B' : null
}
Copy the code
148. Create a counter object
Bigfrontend. Dev/useful/problem /…
function createCounter() {
const obj = { _count: 0 }
return Object.defineProperties(obj, {
count: {
get () {
const r = obj._count
obj._count += 1
return r
}
}
})
}
Copy the code
149. interpolation
Bigfrontend. Dev/useful/problem /…
function t(translation, data = {}) {
return translation.replace(/ {{(. *?) }}/g.(_, key) = > data[key] || ' ')}Copy the code
151. The realization of an Array. The prototype. The map ()
Bigfrontend. Dev/useful/problem /…
Array.prototype.map() can specify this for callback execution
Array.prototype.myMap = function(callback, thisArg) {
const result = []
const that = thisArg || this
this.forEach(function (item, i) {
result[i] = callback.call(that, item, i, that)
})
return result
}
Copy the code
152. Find the largest first k elements
Bigfrontend. Dev/useful/problem /…
Heap sort, divide and conquer
/ / partition
/* * @param {number[]} arr * @param {number} k * @returns {number[]} */
function topK(arr, k) {
if(! arr.length)return []
let result = []
let i = 1
const divideAndConquer = function (arr, base, k) {
console.log(arr)
if (arr.length === 1) {
return arr[0]}const max = []
const min = []
let maxLen = 0
const referenceValue = arr[0]
for (let i = 1; i < arr.length; i += 1) {
if (arr[i] > referenceValue) {
max.push(arr[i])
} else {
min.push(arr[i])
}
}
max.push(referenceValue)
maxLen = max.length + base
if (maxLen >= k && max.length) {
return divideAndConquer(max, base, k)
} else if (maxLen < k && min.length) {
return divideAndConquer(min, maxLen, k)
}
}
while (i <= k && i <= arr.length) {
result.push(divideAndConquer(arr, 0, i))
i += 1
}
return result
}
Copy the code
153. uglify CSS class names
Bigfrontend. Dev/useful/problem /…
/ * * *@returns {string}* /
function getUniqueClassName() {
const letterSet = ['a'.'b'.'c'.'d'.'e'.'f'.'g'.'h'.'i'.'j'.'k'.'l'.'m'.'n'.'o'.'p'.'q'.'r'.'s'.'t'.'u'.'v'.'w'.'x'.'y'.'z'.'A'.'B'.'C'.'D'.'E'.'F'.'G'.'H'.'I'.'J'.'K'.'L'.'M'.'N'.'O'.'P'.'Q'.'R'.'S'.'T'.'U'.'V'.'W'.'X'.'Y'.'Z',]
const letterSetLength = letterSet.length
let prefix = ' '
let className = letterSet[getUniqueClassName.index]
// The final boundary case
if (getUniqueClassName.prefix.length === letterSetLength) {
return ' '
}
for (let i = 0; i < getUniqueClassName.prefix.length; i += 1) {
prefix += letterSet[getUniqueClassName.prefix[i]]
}
getUniqueClassName.index += 1
if (getUniqueClassName.index === letterSetLength) {
getUniqueClassName.index = 0
if(! getUniqueClassName.prefix.length) { getUniqueClassName.prefix.push(0)}else {
if (getUniqueClassName.prefix.every(item= > item === letterSetLength - 1)) {
getUniqueClassName.prefix = getUniqueClassName.prefix.map(() = > 0)
getUniqueClassName.prefix.push(0)}else {
for (let i = getUniqueClassName.prefix.length - 1; i >= 0; i -= 1) {
if (getUniqueClassName.prefix[i] < letterSetLength - 1) {
getUniqueClassName.prefix[i] += 1
break
}
}
}
}
}
return prefix + className;
}
getUniqueClassName.reset = function () {
getUniqueClassName.prefix = []
getUniqueClassName.index = 0
}
// The prefix length
getUniqueClassName.prefix = []
getUniqueClassName.index = 0
Copy the code
154. Simple implementation of two-way binding two-way binding
/ * * *@param {{value: string}} state
* @param {HTMLInputElement} element* /
function model(state, element) {
element.value = state.value;
Object.defineProperty(state, 'value', {
get: () = > element.value,
set: (value) = > element.value = value,
})
}
Copy the code
155. Please implement a count function
Bigfrontend. Dev/useful/problem /…
function count() {
count.count += 1
return count.count
}
count.reset = function () {
count.count = 0
}
count.count = 0
Copy the code
156. Please implement_.set()
Bigfrontend. Dev/useful/problem /…
function set(obj, path, value) {
// String path and array path are changed to array path
if (typeof path === 'string') {
path = path.split('. ')}const newPath = []
const reg = /^([A-Za-z]+)\[([0-9]+)]$/g
let current = obj
let laskKey = ' '
const isNumberKey = function (key) {
// Is a numeric key
const isNumberKey = !isNaN(Number(key))
Key: 1 is valid, 01 is invalid
return isNumberKey && (Number(key) + ' ' === key)
}
for (let i = 0; i < path.length; i += 1) {
if (path[i].includes('[')) {
const arr = reg.exec(path[i])
newPath.push(arr[1])
newPath.push(arr[2])}else {
newPath.push(path[i])
}
}
laskKey = newPath[newPath.length - 1]
for (let i = 0; i < newPath.length - 1; i += 1) {
const key = newPath[i]
const nextKey = newPath[i + 1]
const v = current[key]
if (v instanceof Object) {
current = v
} else {
if (isNumberKey(nextKey)) {
current[key] = []
} else {
current[key] = {}
}
current = current[key]
}
}
current[laskKey] = value
return obj
}
Copy the code
157. Semver comparison
Bigfrontend. Dev/useful/problem /…
Compare versions
/ * * *@param {string} v1
* @param {string} v2
* @returns 0 | 1 | -1
*/
function compare(v1, v2) {
let result = 0
const reg = / [0-9] + \. \. ([0-9] +)/([0-9] +)
const v1Arr = []
const v2Arr = []
for (let i = 1; i <= 3; i += 1) {
v1Arr.push(Number(reg.exec(v1)[i]))
v2Arr.push(Number(reg.exec(v2)[i]))
}
for (let i = 0; i < v1Arr.length; i += 1) {
if (v1Arr[i] > v2Arr[i]) {
result = 1
break
} else if (v1Arr[i] < v2Arr[i]) {
result = -1
break}}return result
}
Copy the code
158. Return the “left” element in the DOM Tree
Bigfrontend. Dev/useful/problem /…
BFS traversal
/ * * *@param {Element} root
* @param {Element} target
* @return {Elemnt | null}* /
function previousLeftSibling(root, target) {
let result = null
const bfs = (nodes) = > {
if (nodes.length) {
let childrenArr = []
let index = null
for (let i = 0; i < nodes.length; i += 1) {
const children = [...nodes[i].children]
childrenArr = [...childrenArr, ...children]
}
for (let i = 0; i < childrenArr.length; i += 1) {
if (childrenArr[i] === target) {
index = i - 1
if(index ! = = -1) {
result = childrenArr[index]
}
}
}
if (index === null) {
bfs(childrenArr)
}
}
}
bfs([root])
return result
}
Copy the code
159. Realize promisify ()
Bigfrontend. Dev/useful/problem /…
Callback is the last parameter
/ * * *@param {(... args) => void} func
* @returns {(... args) => Promise* /
function promisify(func) {
return function(. args) {
const that = this
return new Promise(function(resolve, reject) {
func.apply(that, [...args, function (error, data) {
if (error) {
reject(error)
} else {
resolve(data)
}
}])
})
}
}
Copy the code
162. Please find integers that are not repeated
Bigfrontend. Dev/useful/problem /…
Use bitwise operators
/ * * *@param {number[]} arr
* @returns number* /
function findSingle(arr) {
let result = arr[0]
for (let i = 1; i < arr.length; i += 1) {
result = result ^ arr[i]
}
return result
}
Copy the code