There are some issues in JavaScript (for example: throttling functions, anti-shake functions, recursive functions, etc.) that are often discussed. This chapter will introduce you to 5 common functions in the process of learning to use JavaScriptz. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.
Array flattening
There are many methods for array flattening, but in the end the best method is recursion to achieve a specified depth of flattening Method, so that you will understand the basic routines.
function flattenDepth(array, depth = 1) { let result = [] array.forEach(item => { let d = depth if (Array.isArray(item) && d > 0) { result.push(...(flattenDepth(item, --d))) } else { result.push(item) } }) return result } console.log(flattenDepth([1, [2, [3, [4]], 5]])) // [ 1, 2, [ 3, [ 4 ] ], 5 ] console.log(flattenDepth([1, [2, [3, [4]], 5]], 2)) // [ 1, 2, 3, [ 4 ], 5 ] console.log(flattenDepth([1, [2, [3, [4]], 5]], 3)) // [ 1, 2, 3, 4, 5 ]
The recursive implementation is very simple and easy to understand, that is, traversing each item. If an item is an array, let the item continue to be called. Depth is specified here as the flattening depth, because this parameter is important for the array. Every item of has a role to play, so it is placed inside the loop.
Currying
Currying of functions has been talked about badly. Everyone has their own understanding and implementation method. In one sentence The explanation is that if there are enough parameters, it will be executed. If there are not enough parameters, a function will be returned. The previous parameters will be stored until there are enough.
function curry(func) { var l = func.length return function curried() { var args = [].slice.call(arguments) if(args.length < l) { return function() { var argsInner = [].slice.call(arguments) return curried.apply(this, args.concat(argsInner)) } } else { return func.apply(this, args) } } } var f = function(a, b, c) { return console.log([a, b, c]) }; var curried = curry(f) curried(1)(2)(3) // => [1, 2, 3] curried(1, 2)(3) // => [1, 2, 3] curried(1, 2, 3) // => [1, 2, 3]
It is not difficult to see from the above code that each time the number of parameters is judged, it is compared with the number of curried function parameters. If it is less than the number, it will continue to return to the function, otherwise it will be executed.
Anti-shake
According to my understanding, anti-shake means that no matter how many times you trigger it, it will wait until a period of time you specify after the last trigger. Time is triggered. Following this explanation, write a basic version.
function debounce(func, wait) { var timer return function() { var context = this var args = arguments clearTimeout(timer) timer = setTimeout(function() { func.apply(context, args) }, wait) } }
Now there is a requirement that it will be triggered at the beginning and the last time, and it can be configured. First, write a test page to facilitate testing the function. Each time you press the space bar, the number will increase by 1. Test anti-shake and throttling functions.
<html> <head> <style> #container{text-align: center; color: #333; font-size: 30px;} </style> </head> <body> <div id="container"></div> <script> var count = 1 var container = document.getElementById('container') function getUserAction(e) { // 空格 if (e.keyCode === 32) { container.innerHTML = count++ } } // document.onkeydown = debounce(getUserAction, 1000, false, true) document.onkeydown = throttle(getUserAction, 1000, true, true) function debounce(func, wait, leading, trailing) {} function throttle(func, wait, leading, trailing) {} </script> </body> </html>
Determine whether the start and end are executed through the two parameters leading and trailing. If leading is true, it will be executed once every time you press space. If trailing is true, the last trigger will be triggered every time you end. implement. Anti-shake function distance, if both are true, pressing space for the first time will add 1, and then pressing space quickly, the getUserAction inside will not be executed at this time, but will be executed after letting go. Add trailing to false , it will not be executed after letting go.
function debounce(func, wait, leading, trailing) { var timer, lastCall = 0, flag = true return function() { var context = this var args = arguments var now = + new Date() if (now - lastCall < wait) { flag = false lastCall = now } else { flag = true } if (leading && flag) { lastCall = now return func.apply(context, args) } if (trailing) { clearTimeout(timer) timer = setTimeout(function() { flag = true func.apply(context, args) }, wait) } } }
Explain, each time the time of the last call is recorded, compare it with the current time. If it is less than the interval, it will not be executed after the first execution. If it is greater than the interval or called after the interval, Then reset the flag and compare it with the basic version above.
Throttling
Throttling means, No matter how it is triggered, it will be executed at the specified interval, the same Give me the basic version.
function throttle(func, wait) { var timer return function() { var context = this var args = arguments if (!timer) { timer = setTimeout(function () { timer = null func.apply(context, args) }, wait) } } }
It also adds two parameters like the anti-shake function. You can also use the above example to test. In fact, the codes of the two are very similar.
function throttle(func, wait, leading, trailing) { var timer, lastCall = 0, flag = true return function() { var context = this var args = arguments var now = + new Date() flag = now - lastCall > wait if (leading && flag) { lastCall = now return func.apply(context, args) } if (!timer && trailing && !(flag && leading)) { timer = setTimeout(function () { timer = null lastCall = + new Date() func.apply(context, args) }, wait) } else { lastCall = now } } }
Object copy
We all know that object copy is divided into deep copy and shallow copy. The black technology method is to use
JSON.parse(JSON.stringify(obj))
Another method is to use recursion
function clone(value, isDeep) { if (value === null) return null if (typeof value !== 'object') return value if (Array.isArray(value)) { if (isDeep) { return value.map(item => clone(item, true)) } return [].concat(value) } else { if (isDeep) { var obj = {} Object.keys(value).forEach(item => { obj[item] = clone(value[item], true) }) return obj } return { ...value } } } var objects = { c: { 'a': 1, e: [1, {f: 2}] }, d: { 'b': 2 } } var shallow = clone(objects, true) console.log(shallow.c.e[1]) // { f: 2 } console.log(shallow.c === objects.c) // false console.log(shallow.d === objects.d) // false console.log(shallow === objects) // false
For basic types, return directly. For reference types, traverse and recursively call the clone method.
Summary
In fact, for the above methods, the general idea is the use of recursion and higher-order functions, including closure The front-end likes to ask these questions about the use of packages. It is best to implement it yourself, which will help understanding.
The above is the detailed content of 5 common functions in learning JavaScript. For more information, please follow other related articles on the PHP Chinese website!