This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.
preface
I met my elementary school classmates yesterday and didn’t think it mixed so badly – only put a dollar into my bowl O (╥﹏╥) O
Life is so boring, always amuse yourself is not, later I will often tell you jokes, do you want to listen to not O(∩_∩) haha ~
A few days ago wrote a must-have, senior front-end 】 【 30 + high frequency written questions and detailed answers long (word), see the “how” you baffled me handwritten summarizes 30 + common topic implementation, points out many problems, the brothers and sisters have been made without stabilization and throttling, bighead don’t eat not to sleep and have 12 + handwritten topic (close to 42 +), Take a look.
Through train
Click to view the source address of rigong 1 problem (62+ handwritten problem implementation so far)
1. If you
// Stabilization: this can be combined with the scenario where your computer is set to sleep for 10 minutes
// If you are using the computer all the time, the computer will not sleep (frequently turn off the previous timer, turn on the new timer)
Your computer falls asleep 10 minutes after you haven't used it for the last time
const debounce = function (func, delay) {
let timer = null
return function (. args) {
clearTimeout(timer)
timer = setTimeout(() = > {
func.apply(this, args)
}, delay)
}
}
/ / test
/ / HTML
<input type="text" id="input"/>
/ / js parts
const showName = debounce(function (name) {
console.log($input.value, this, name)
}, 500)
$input.addEventListener('input'.(e) = > {
// Stop input within 500ms before output
showName.call({ name: 'Front End Bighead' }, 'Front End Bighead')})Copy the code
2. The throttle
Throttling: regardless of how you trigger, it will only trigger once in a specified period of time
Timestamp based (Mode 1)
const throttle = function (func, delay) {
let startTime = Date.now()
return function (. args) {
let lastTime = Date.now()
if (lastTime - startTime > delay) {
func.apply(this, args)
startTime = Date.now()
}
}
}
/ / test
let t1 = Date.now()
const showName = throttle(function (name) {
const t2 = Date.now()
console.log(this, name, t2 - t1)
t1 = Date.now()
}, 1000)
// The showName function will be executed every 10 milliseconds, but it will be executed every 1 second
setInterval(() = > {
showName.call({ name: 'Front End Bighead' }, 'Front End Bighead')},10)
// {name: 'bighead'} 'bighead
// {name: 'bighead'} 'bighead' 1001
// {name: 'bighead'} 'bighead' 1006
// {name: 'bighead'} 'bighead' 1006
// {name: 'bighead'} 'bighead' 1005
Copy the code
Based on setTimeout(Method 2)
const throttle2 = function (func, delay) {
let timer = null
return function (. args) {
if(! timer) { timer =setTimeout(() = > {
func.apply(this, args)
timer = null
}, delay)
}
}
}
/ / test
let t1 = Date.now()
const showName = throttle2(function (name) {
const t2 = Date.now()
console.log(this, name, t2 - t1)
t1 = Date.now()
}, 1000)
setInterval(() = > {
showName.call({ name: 'Front End Bighead' }, 'Front End Bighead')},10)
// {name: 'bighead'} 'bighead
// {name: 'bighead'} 'bighead' 1001
// {name: 'bighead'} 'bighead' 1007
// {name: 'headfish'} 'headfish' 1011
// {name: 'bighead'} 'bighead' 1009
// {name: 'bighead'} 'bighead' 1008
Copy the code
3. Coriolization of functions
const curry = (func, ... args) = > {
// Get the number of arguments to the function
const fnLen = func.length
return function (. innerArgs) {
innerArgs = args.concat(innerArgs)
// If the parameters are not collected enough, continue recursive collection
if (innerArgs.length < fnLen) {
return curry.call(this, func, ... innerArgs) }else {
// Otherwise call func with the collected arguments
func.apply(this, innerArgs)
}
}
}
/ / test
const add = curry((num1, num2, num3) = > {
console.log(num1, num2, num3, num1 + num2 + num3)
})
add(1) (2) (3) // 1 2 3 6
add(1.2) (3) // 1 2 3 6
add(1.2.3) // 1 2 3 6
add(1) (2.3) // 1 2 3 6
Copy the code
4. bind
The bind() method creates a new function, and when bind() is called, this of the new function is specified as the first argument to bind(), and the remaining arguments will be used as arguments to the new function. MDN
The sister call implementation
The sister apply implementation
Function.prototype.bind2 = function (context, ... args) {
if (typeof this! = ='function') {
throw new TypeError('Bind must be called on a function')}const executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
if(! (callingContextinstanceof boundFunc)) {
// If the call method is not new func, call sourceFunc directly and give the corresponding argument
return sourceFunc.apply(context, args)
} else {
// Similar to several procedures for executing new
const self = Object.create(sourceFunc.prototype) // Handle the form of the new call
const result = sourceFunc.apply(self, args)
// If the result is not an object function, return self
if (result && typeof result === 'object' || typeof result === 'function') {
return result
} else {
return self
}
}
}
const func = this
const bound = function (. innerArgs) {
return executeBound(func, bound, context, this, args.concat(innerArgs))
}
return bound
}
/ / test
// 1. Common call
const showName = function (sex, age) {
console.log(this, sex, age)
}
showName.bind2({ name: 'Front End Bighead' }, 'boy') (100) // { name: '前端胖头鱼' } 'boy' 100
// 2. new call
const Person = function (name) {
this.name = name
}
Person.prototype.showName = function (age) {
console.log(this.this.name, age)
}
const bindPerson = Person.bind(null.'boy')
const p1 = new bindPerson('Front End Bighead')
p1.showName(100) // Person { name: 'boy' } 'boy' 100
Copy the code
5. Implement a simplified template engine
In the era of jQuery, the template engine is still used a lot. It can be understood as a function that takes the template + data through a black box operation and finally gets the page to be displayed
const render = (template, data) = > {
// \s*? {{name}} {{name}
return template.replace(/{{\s*? (\w+)\s*? }}/g.(match, key) = > {
// Replace is read if a match is found, otherwise empty string is replaced
return key && data.hasOwnProperty(key) ? data[ key ] : ' '})}const data = {
name: 'Front End Bighead'.age: 100
}
const template = 'I am: {{name}} age is: {{age}}'
console.log(render(template, data))
/* I am: front-end bighead fish age is: 100 */
Copy the code
6. Four ways to convert a class array to an array
// Class arrays are converted to arrays
const arrayLikeObj = {
0: 'Front End Bighead'.1: 100.length: 2
}
// 1. [].slice
console.log([].slice.call(arrayLikeObj))
// 2. Array.from
console.log(Array.from(arrayLikeObj))
// 3. Array.apply
console.log(Array.apply(null, arrayLikeObj))
// 4. [].concat
console.log([].concat.apply([], arrayLikeObj))
Copy the code
7. Please implement DOM2JSON a function that can output a DOM node in JSON format
Has appeared in byte’s interview
const dom2json = (rootDom) = > {
if(! rootDom) {return
}
let rootObj = {
tagName: rootDom.tagName,
children: []}const children = rootDom.children
// Read the child node (element node)
if (children && children.length) {
Array.from(children).forEach((ele, i) = > {
// recursive processing
rootObj.children[ i ] = dom2json(ele)
})
}
return rootObj
}
Copy the code
test
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>dom2json</title>
</head>
<body>
<div class="box">
<p class="p">hello world</p>
<div class="person">
<span class="name">Front end bighead fish</span>
<span class="age">100</span>
</div>
</div>
<script>
const dom2json = (rootDom) = > {
if(! rootDom) {return
}
let rootObj = {
tagName: rootDom.tagName,
children: []}const children = rootDom.children
if (children && children.length) {
Array.from(children).forEach((ele, i) = > {
rootObj.children[ i ] = dom2json(ele)
})
}
return rootObj
}
const json = dom2json(document.querySelector('.box'))
console.log(json)
</script>
</body>
</html>
Copy the code
8. List to tree structure
I believe you have encountered similar problems in your work. The front end needs data in a tree structure, but the back end returns a list. We need to convert the list into a tree structure (of course, here you can also tell your back end classmates why they don’t give me the data I want).
const arrayToTree = (array) = > {
const hashMap = {}
let result = []
array.forEach((it) = > {
const { id, pid } = it
// If the tree does not exist, declare the children tree first
// This step may also appear below
if(! hashMap[id]) { hashMap[id] = {children: [] } } hashMap[id] = { ... it,children: hashMap[id].children
}
// Process the current item
const treeIt = hashMap[id]
// Root node, push directly
if (pid === 0) {
result.push(treeIt)
} else {
// It is also possible that the parent node of the current node has not yet joined the hashMap and needs to be handled separately
if(! hashMap[pid]) { hashMap[pid] = {children: []}}// If it is not the root node, find the parent node and insert yourself into the children of the parent node
hashMap[pid].children.push(treeIt)
}
})
return result
}
/ / test
const data = [
// Note that the element with pid 1 is placed first
{ id: 2.name: '2'.pid: 1 },
{ id: 1.name: '1'.pid: 0 },
{ id: 3.name: '3'.pid: 1 },
{ id: 4.name: '4'.pid: 3 },
{ id: 5.name: '5'.pid: 4 },
{ id: 7.name: '7'.pid: 6},]console.log(JSON.stringify(arrayToTree(data), null.2))
/ * [{" id ": 1," name ":" unit 1 ", "pid" : 0, "children" : [{" id ": 2," name ":" department 2 ", "pid" : 1, "children" : []}, {" id ": Department of 3, "name" : "3", "pid" : 1, "children" : [{" id ": 4," name ":" unit 4 ", "pid" : 3, "children" : [{" id ": 5," name ": Department of "5", "pid" : 4, "children" :}}}} []]]]] * /
Copy the code
9. Tree structure transfer list
You can try it the other way around
const tree2list = (tree) = > {
let list = []
let queue = [...tree]
while (queue.length) {
// Start fetching nodes from the front
const node = queue.shift()
const children = node.children
// Take the children of the current node and queue them for the next loop
if(children.length) { queue.push(... children) }// Delete the extra children tree
delete node.children
// Add to the list
list.push(node)
}
return list
}
/ / test
const data = [
{
"id": 1."name": Department of "1"."pid": 0."children": [{"id": 2."name": "Department of 2"."pid": 1."children": []}, {"id": 3."name": "Unit 3"."pid": 1."children": [{"id": 4."name": "Department of 4"."pid": 3."children": [{"id": 5."name": Department of "5"."pid": 4."children": []}]}]}]console.log(tree2list(data))
/ * [{id: 1, name: '1', pid: 0}, {id: 2, name: '2', pid: 1}, {id: 3, name: '3', pid: 1}, {id: 4, name: '4', pid, 3}, {5, id: name: '5', pid: 4}] * /
Copy the code
10. sleep
Implement a function, n seconds after the function func
const sleep = (func, delay) = > {
return new Promise((resolve) = > {
setTimeout(() = > {
resolve(func())
}, delay)
})
}
const consoleStr = (str) = > {
return () = > {
console.log(str)
return str
}
}
const doFns = async() = > {const name = await sleep(consoleStr('Front End Bighead'), 1000)
const sex = await sleep(consoleStr('boy'), 1000)
const age = await sleep(consoleStr(100), 1000)
console.log(name, sex, age)
}
doFns()
// Front-end bighead fish 1s later
// boy 2s later
// 100 3s later
// Front end Bighead boy 100
Copy the code
Fibonacci series
Fibonacci numbers, usually denoted by F(n), form a sequence called the Fibonacci sequence. The series consists of0 和 1At the beginning, each of the following numbers is the sum of the preceding two. So that's F of0) = 0, F (1) = 1
F(n) = F(n - 1) + F(n - 2), where n >1I give you n, please calculate F(n). The sample1Input:2Output:1Explanation: F (2) = F(1) + F(0) = 1 + 0 = 1The sample2Input:3Output:2Explanation: F (3) = F(2) + F(1) = 1 + 1 = 2The sample3Input:4Output:3Explanation: F (4) = F(3) + F(2) = 2 + 1 = 3
Copy the code
Violence to achieve
According to the problem, it is easy to write the following recursive violence code
const fib = (n) = > {
if (n === 0) {
return 0
}
if (n === 1 || n === 2) {
return 1
}
return fib(n -2) + fib(n - 1)}/ / test
console.log(fib(1)) / / 1
console.log(fib(2)) / / 1
// Try counting the computation time
const t1 = Date.now()
console.log(fib(44)) / / 701408733
console.log(Date.now() - t1) / / close to 4393
Copy the code
Cache optimization
The code above does the trick, but the performance is not good. Let’s look at a procedure to calculate fib(10)
10 / / calculation
10= >9 + 8 // We need to calculate 9 and 8
9= >8 + 7 // We need to calculate 8 and 7
8= >7 + 6 // Need to calculate 7 and 6
7= >6 + 5 // We need to calculate 6 and 5
6= >5 + 4 // We need to calculate 5 and 4
5= >4 + 3 // We need to calculate 4 and 3
4= >3 + 2 // We need to calculate 3 and 2
2= >1 + 0 // Need to calculate 1 and 0
Copy the code
In this process, the code that follows the above violence will repeat several times some of the previously calculated values, such as 8, 7, 6, 5… Wait, this loss is not necessary, so we can cache the results of the calculation, and the next time we find the same value, just return it
const fib = (n) = > {
// Cache returns directly
if (typeoffib[ n ] ! = ='undefined') {
return fib[ n ]
}
if (n === 0) {
return 0
}
if (n === 1 || n === 2) {
return 1
}
const res = fib(n -2) + fib(n - 1)
// Cache the result of the calculation
fib[ n ] = res
return res
}
console.log(fib(1)) / / 1
console.log(fib(2)) / / 1
const t1 = Date.now()
console.log(fib(44)) / / 701408733
console.log(Date.now() - t1) // 1ms
Copy the code
12. Implement the sum function
Implement a function sum that satisfies this rule
sum(1.2.3).valueOf() / / 6
sum(2.3) (2).valueOf() / / 7
sum(1) (2) (3) (4).valueOf() / / 10
sum(2) (4.1) (2).valueOf() / / 9
Copy the code
Analysis of the
A close look at these calls yields the following information
-
The sum function can take one or more arguments
-
The sum function returns a new function and can pass one or more arguments
-
The final calculation is done when.valueof is called
Does this look like a function corrification? The previous function call simply caches the arguments of each call, whereas the valueOf call takes the arguments and sums them up once and returns the result
const sum = (. args) = > {
// Add is used to cache parameters
// Note that after the add call is complete, the add function itself is returned so that it can be called chained
const add = (. args2) = > {
args = [ ...args, ...args2 ]
return add
}
// Sum calculation
add.valueOf = () = > args.reduce((ret, num) = > ret + num, 0)
return add
}
/ / test
console.log(sum(1.2.3).valueOf()) / / 6
console.log(sum(2.3) (2).valueOf()) / / 7
console.log(sum(1) (2) (3) (4).valueOf()) / / 10
console.log(sum(2) (4.1) (2).valueOf()) / / 9
Copy the code
At the end
“Welcome to the discussion in the comments section. The excavation authorities will draw 100 nuggets in the comments section after project Diggnation. See the event article for details.”