The author has been systematically combing the knowledge of native JS recently, because I think JS, as the fundamental technology of front-end engineers, can't be learned too many times. I plan to make a series driven by a series of questions. Of course, there will be questioning and expansion. The content is systematic and complete. It will improve junior high school players, and senior players will be reviewed and consolidated.
Chapter 1: the difference and implementation of debounce and throttle
During our normal development, there are many scenarios that frequently trigger events, such as real-time request from search box, onmousemove, resize, onscroll, etc. sometimes, we can't or don't want to trigger events frequently. What should we do? At this time, function anti chattering and function throttling should be used
Debounce
The function will only execute once within n milliseconds after triggering the high-frequency event. If the high-frequency event is triggered again within N seconds, the time will be recalculated
Feature after using anti shake processing, if you input it again within 500 milliseconds, the timing will restart
The operation with frequent communication will not be executed until the interval between operations is greater than n milliseconds. The second operation can be carried out. The execution interval is > = n
Popular core idea: delete the original timer and create a new timer * * each time an event is triggered. Similar to the return function of King glory * *, if you repeatedly trigger the return function, only recognize the last time and count from the last trigger
! [debounce anti shake. PNG]( https://img-blog.csdnimg.cn/img_convert/63a5d82e661db679b71efea3e7e436c3.png#height=304&id=WrjvZ&name=debounce Anti shake png&originHeight=304&originWidth=622&originalType=binary&ratio=1&size=19307&status=done&style=none&width=622)
function debounce(fn, delay) { let timer = null; return function (...args) { let context = this; if (timer) clearTimeout(timer); timer = setTimeout(function () { fn.apply(context, args); }, delay); } }
Scenario application example
<body> <input type="text" value=""> </body> <script> document.querySelector("input").oninput = debounce(function (data) { console.log(this.value,data); }) function debounce(fn,time=500) { let timer = null // Used to store the return value of the timer return function () { clearTimeout(timer) // Clear the previous timer every time anti shake is triggered timer = setTimeout(() => { fn.apply(this, arguments) // In order to set the table context to the current this }, time) } } </script>
Applicable scenarios, such as the content entered in the user search box, such as the content entered in the user search box. Without anti shake, each user will send a request to the background. After anti shake is used, the request will not be sent until the user's input is completed, so as to reduce the pressure on the server
Throttle
It is triggered by a high-frequency event, but it is executed once in n seconds, so throttling will dilute the execution frequency of the function
Feature no matter how you enter, the function is triggered every xxx milliseconds
The communication is executed once every n milliseconds, and the interval = n milliseconds
Popular core idea: if it is triggered again within the time range of the timer, it will be ignored. The next timer task can be started only after the current timer is completed. It's like a bus. It runs every 10 minutes. No matter how many people wait for me at the bus stop within 10 minutes, I'll leave as soon as I arrive in 10 minutes!
! [throttle. PNG]( https://img-blog.csdnimg.cn/img_convert/0d12090086707b1c45cae250a5430fba.png#height=323&id=YlV6t&name=throttle Throttling png&originHeight=323&originWidth=717&originalType=binary&ratio=1&size=18281&status=done&style=none&width=717)
function throttle(fn, interval = 500) { let flag = true; return function (...args) { let context = this; if (!flag) return; flag = false; setTimeout(() => { fn.apply(context, args); flag = true; }, interval); }; }; // The same meaning is expressed in the following way: const throttle = function (fn, interval = 500) { let last = 0; return function (...args) { let context = this; let now = +new Date(); // It's not time yet if (now - last < interval) return; last = now; fn.apply(this, args) } }
Enhanced throttling (anti shake + throttling)
function throttle(fn, delay = 500) { let last = 0, timer = null; return function (...args) { let context = this; let now = new Date(); if (now - last < delay) { clearTimeout(timer); timer = setTimeout(function () { last = now; fn.apply(context, args); }, delay); } else { // This time indicates that the time has come and a response must be given last = now; fn.apply(context, args); } } }
Scenario application example
<input type="text" value=""> <script> document.querySelector("input").oninput = throttle(function (data) { console.log(this.value, data); }) function throttle(fn) { let canRun = false //Record whether there is a function to be executed return function () { if (canRun) return // If it returns directly within the cycle of the timer, it is not executed canRun = true setTimeout(() => { fn.apply(this, arguments) canRun = false // If it is set to false after running, it means that the function is running and the timer is empty. The next function can be performed }, 1000) } } </script>
<body style="height: 10000px;"> </body> <script> window.addEventListener('scroll', throttle(handle(), 1000)) function throttle(fn, delay) { var timer = null, startTime = Date.now() //Set start time return function () { var currentTime = Date.now() var context = this var args = arguments var remaining = delay - (currentTime - startTime) //Remaining time clearTimeout(timer) if (remaining <= 0) { // When the interval is greater than the set delay fn.apply(context, args) startTime = currentTime } else { timer = setTimeout(function () { fn.apply(context, args) }, remaining) //Cancels the current counter and calculates a new remaining } } } function handle() { var count = 1; return function (e) { console.log(++count, e) } } </script>
- Applicable scenario
- Lazy load monitor browser scroll position
- Implementation of the drag and drop function of DOM elements (mousemove)
- mousedown/keydown event of shooting game (only one bullet can be fired per unit time)
- Calculate the distance the mouse moves (mousemove)
- Canvas simulation Sketchpad function (mousemove)
- Search Association (keyup)
- Listen to the scrolling event to determine whether to automatically load more at the bottom of the page: after adding debounce to the scroll, you will judge whether to reach the bottom of the page only after the user stops scrolling; If it is a throttle, it will be judged at intervals as long as the page scrolls
Chapter 2: regular multi keyword highlighting
<body> </body> <script> function format(text, formatText) { var a = formatText.sort((a, b) => b.length - a.length); return text.replace(new RegExp('(' + a.join('|') + ')', 'g'), '<span class="red">$1</span>') } // const formatText = ["Tencent cloud", "cloud", "cloud service", "cloud"] // const text = "Tencent cloud is a cloud computing service launched by Tencent. It publishes the cloud map of global cloud services, builds data center nodes covering the world, and works with global partners in more regions to provide cloud services for Chinese overseas enterprises and overseas local enterprises." const formatText = ["development", "Front end development", "Developer Programmer ","Front end developer"] const text = "A breeze,yes JavaScript Technical Daniel,He developed many projects,I'm a front-end developer,Engaged in front-end development,He is a development programmer" var div = document.createElement('div') div.innerHTML = format(text, formatText) document.body.appendChild(div); </script> <style> .red { color: red; } </style>
Chapter 3: String template
function render(template, data) { const reg = /\{\{(\w+)\}\}/ // Template string regular if (reg.test(template)) { // Determine whether there is a template string in the template const name = reg.exec(template)[1] // Find the field of the first template string in the current template template = template.replace(reg, data[name]) // Render the first template string return render(template, data) // Render recursively and return the rendered structure } return template // If the template has no template string, it is returned directly } let template = 'I am{{name}},Age{{age}},Gender{{sex}}' let person = { name: 'Bran', age: 12, sex: 'female' } console.log(render(template, person)) // I'm bran, age 12, gender female
Chapter 4: parsing URL parameters as objects
//Get the url? All parameters after export function getURLLocationSearch() { var adataSource = location.search.substr(1).split('&'); var obj = {}; adataSource.forEach(function(item, i) { var pairList = item.split('='); obj[pairList[0]] = pairList[1]; }); return obj; } // Get URL address? Return a dictionary after the parameter export function decodeLocationSearch() { var search = decodeURI(document.location.search); return search .replace(/(^\?)/, '') .split('&') .reduce(function(result, item) { var values = item.split('='); result[values[0]] = values[1]; return result; }, {}); //The following {} result is the second parameter of {} render, and item is traversal } // Get URL address? Return a dictionary after the parameter function parseParam(url) { const paramsStr = /.+\?(.+)$/.exec(url)[1]; // Will? Take out the following string const paramsArr = paramsStr.split('&'); // Split the string with & and save it in the array let paramsObj = {}; // Save params to object paramsArr.forEach(param => { if (/=/.test(param)) { // Handle parameters with value let [key, val] = param.split('='); // Split key and value val = decodeURIComponent(val); // decode val = /^\d+$/.test(val) ? parseFloat(val) : val; // Determine whether to convert to number if (paramsObj.hasOwnProperty(key)) { // If the object has a key, add a value paramsObj[key] = [].concat(paramsObj[key], val); } else { // If the object does not have this key, create the key and set the value paramsObj[key] = val; } } else { // Processing parameters without value paramsObj[param] = true; } }) return paramsObj; }
Convert the key value pairs of the dictionary into spliced URLs
//Convert the key value pairs of the dictionary into spliced URLs {key1: value1, key2: Value2} = = >? key1=value1&key2=value2 export function encodeLocationSearch(params: any) { let data_arr = []; for (let key in params) { data_arr.push(key + '=' + params[key]); } return '?' + data_arr.join('&'); }
Regular matching URL address? Single parameter after
//Todo Kim stamp regular matching URL address? Single parameter after // i case insensitive; // g global matching; // m-line more matching; // s special character dot Contains a newline character; // U matches only the nearest string; No duplicate matching; // The default dot Is to match any single character except the newline \ n, plus s Contains newline characters // [modifier] // x ignore the blank space in the mode; // A force matching from the beginning of the target string; // D if $is used to limit the ending character, line breaks at the end are not allowed; // e fit function preg_replace() can be used to execute the matched string as a regular expression; export function getParameter(params: any, datasource = location.search) { var re = new RegExp(params + '=([^&]*)', 'i'); var a = re.exec(datasource); if (a == null) { return null; } return a[1]; }
Chapter V: UUID code
export function generateUUID() { var d = new Date().getTime(); if (window.performance && typeof window.performance.now === 'function') { d += performance.now(); //use high-precision timer if available } var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16); }); return uuid; }
Chapter 6: regular cookie acquisition
//Regular get cookie export function getCookie(name: any) { //var res = document.cookie.match(/\bcsrf_token=([^;]*)\b/) var res = document.cookie.match('\\b' + name + '=([^;]*)\\b'); return res ? res[1] : undefined; }