preface
This article sorted out the front-end interview frequently appeared handwritten JS related topics, if the answer to the students have different views welcome to add discussion in the comments section, of course, there are questions, also welcome to point out in the comments section.
Remember: these js hand-written records, the writer do before, think about these methods are used to do, what you need to pass parameters, return what, you also need to pay attention to some boundary conditions, it has a great test on the basis of js, the foundation is bad, be sure to take a lot more js (especially, prototype chain, this point, promise, inheritance, etc.)
- This article speak prototype chain very well blog.csdn.net/cc188688768…
- Js points to the problem juejin.cn/post/684490…
- Six ways to inherit js juejin.cn/post/699693…
- Promise —–> Subsequent updates
Learning is that simple. Do you understand me?
Quote and reference: thanks to the two big guys and the whole nuggets of the author help, let me harvest a lot juejin.cn/post/696871… Juejin. Cn/post / 684490…
1. Implement the new operator
New produces an instance object with its own Proto property, and the instance’s ProTO points to the constructor’s prototype
// Pass in the constructor and constructor parameters
function myNew(fun,... args){
// Initialize an object and allocate space
const obj = {};
// Link to the function prototype
obj.__proto__ = fun.prototype;
SetPrototypeOf (obj, fun.prototype)
// bind obj to the constructor and pass in the remaining arguments
const res = fun.apply(obj,args);
// Returns the constructed object, especially if res returns a non-empty object
return res instanceof Object ? res : obj
Return (typeof res! == null && typeof res === 'object')? res:obj;
}
function Animal(name) {
this.name = name;
}
let animal = myNew(Animal, 'dog');
console.log(animal.name) // dog
Copy the code
2. Implement instanceOf
function myInstanceof(left,right){
// Verify that if it is a basic data type, return false directly
const baseType = ['string'.'number'.'boolean'.'undefined'.'symbol']
if(baseType.includes(typeof(left))) return false;
const prototype = right.prototype;
let proto = left.__proto__;
while(true) {
if(proto===null) return false;// Find the top layer
if(proto===prototype) return true;
proto = proto.__proto__;// If not, continue to search one level up the prototype chain}}function Func(){
console.log('hzy')}let fun = new Func();
myInstanceof(fun,Function);
Copy the code
3. Implement shallow/deep copy
- Shallow copy: Copies Pointers to objects, and changes affect each other
- Deep copy: Copies the entire object to another memory without affecting the modification
Shallow copy method
- Concat () and slice(0) and expander (…) And the Object. The assign ()
let arr = [1.3, {
username: 'kobe'
}];
let arr2 = arr.concat();
//let arr2 = arr.slice(0);
//let arr2 = [...arr]
//let arr2 = Object.assign([], arr); Merge objects
arr2[2].username = 'wade';
console.log(arr); //[ 1, 3, { username: 'wade' } ]
Copy the code
Deep copy method
Parse (json.stringify (arr))
let arr = {
a: 1.b: [ 'e'.'f'.'g'].c: { h: { i: 2}}};let arr2 = JSON.parse(JSON.stringify(arr));
arr2[2].username = 'wade';
console.log(arr); //[ 1, 3, { username: 'kobe' } ]
/ / disadvantages:
//1. He cannot clone functions, RegExp and other special objects
//2. Discard the Object's constructor; all constructors point to Object
//3. The object has a circular reference and an error will be reported
/ / such as:
const arr = {
a: say,
b: new Array(1),
c: new RegExp('ab+c'.'i'),
d: Messi
};
Copy the code
Method 2: Basic approach (defect as above)
function deepClone(target) {
if (typeof target === 'object') {
let cloneTarget = Array.isArray(target) ? [] : {};
for (const key in target) { // Iterate over objects with... The in...
cloneTarget[key] = deepClone(target[key]);
}
return cloneTarget;
} else {
returntarget; }};const target = {
field1: 1.field2: undefined.field3: 'hzy'.field4: {
child: 'child',},field5: [2.4.8]};let arrCopy =deepClone(target);
target['one'] = 5
console.log(target,arrCopy)
Copy the code
4. Implement apply, call and bind
Apply method implementation
1Realization effectfunction fn(age){
this.age = age
}
let target = {name:'hzy'}
fn.myApply(target,[18.3]) / / with fn. Apply (target, 18, 3)
console.log(target) //{ name: 'hzy', age: 18 }
2Analyze the apply principle// Two arguments, fn constructor, args parameter array
//myApply should hang on function.prototype
// If no argument is passed, target will default to window, and args will default to [].
// Execute the function by specifying this to target.fn and passing in the given argument
// Delete the fn function from target
3Code implementationFunction.prototype.myApply = function (target,args){
// this: [Function: fn]
if(typeof this! = ='function') {throw new TypeError('not a function')}// If no argument is passed, target will default to window, and args will default to [].
target = target || window;
args = args || [];
target.fn = this; //target: {name: 'hzy', fn: [Function: fn]}target.fn(... args)// Execute the fn function in target
delete target.fn // Delete the fn function from target
return target
}
Copy the code
Call method implementation
The difference between apply and call is that the apply parameters are arrays and the call parameters are separated by commas
Bind method implementation
Fn. bind(obj,arg1,arg2) creates a new binding function. Fn will not execute immediately, while call, apply will execute immediately
Bind (obj,arg1).bind(arg2,arg3).bind(arg4)
// The bind implementation is a little more complicated because it takes into account more cases and involves parameter merging (similar to function currification)
Function.prototype.myBind = function (target,... args){
if(typeof this! = ='function') {throw new TypeError('not a function')}const self = this; // Store the source function and its parameters
// secondArgs is secondArgs
let fnToBind = function (. secondArgs){
// Check whether this is an instance of the fnToBind binding function
// The function called by new refers to the current function, otherwise it is bound to the passed target
let context = this instanceof fnToBind ? this : Object(target);
// Call the source function with this and pass the argument, return the result of execution
returnself.call(context,... args,... secondArgs); }if (self.prototype) {
// Copy the source function's prototype to fnToBind. Some functions have no prototype, such as the arrow function
fnToBind.prototype = Object.create(self.prototype);
}
return fnToBind; // Return the bound function
}
let obj = { name: "hzy" }
function test(x,y,z) {
console.log(this.name) // ciel
console.log(x+y+z) / / 6
}
let Bound = test.myBind(obj,1.2)
Bound(3) // Repeat parameter 3 => 6
/ / test
let obj = { name: "hzy" }
function test(x,y,z) {
console.log(this.name) // ciel
console.log(x+y+z) / / 6
}
let Bound = test.myBind(obj,1.2)
Bound(3) // Repeat parameter 3 => 6
Copy the code
Implement object.create ()
New produces an instance object with its own Proto property, and the instance’s ProTO points to the constructor’s prototype
1Realization effectconsole.log(myCreate({a:2}).__proto__) //{ a: 2 }The equivalent ofObject.create({a:2})
2, analysis,ObjectThe create () principleObjectThe.create() method creates a new object, using an existing object to provide the __proto__ of the newly created object3Code implementationfunction create(proto) {
function F() {}
F.prototype = proto;
return new F();
}
Copy the code
Parse and JSON. Stringify
JSON.parse()
- Eval () is possible, but there are XSS vulnerabilities
eval('(' + target + ') ');
Copy the code
- JSON. The parse () half an hour to implement tutorial: zhuanlan.zhihu.com/p/28049617
JSON.stringify()
function myStringify(target) {
if (typeoftarget ! = ='object' || target === null) {
// Special handling of strings, multiple double quotes
if(typeof target==='string') {return `"${target}"`
}else{
return String(target); }}else{
// Handle objects and arrays
const json = [];
for(let key in target){
let value = target[key];
if(Array.isArray(target)){
json.push(`${myStringify(value)}`)}else{
json.push(`"${key}":${myStringify(value)}`)}}// Note that when an array or object is converted to a string, the parentheses are lost
if (Array.isArray(target)) {
return ` [${json}] `
} else {
return ` {${json}} `}}}console.log(myStringify('string'))
// "string"
console.log(myStringify(Awesome!))
/ / 666
console.log(myStringify({name1: {name2: "abc"}}))
// {"name1":{"name2":"abc"}}
console.log(myStringify([1."false".false]))
// [1,"false",false]
Copy the code
7. Sort version numbers
A set of version number [‘, ‘while’, ‘while’, ‘0.1.1.1’, ‘2.2’, ‘4.3.5], arranged in this [‘,’ while ‘, ‘while’, ‘0.1.1.1’, ‘2.2’, ‘4.3.5]
let arr = [' '.'0.1.1'.'0.1.1'.'0.1.1.1'.'2.2'.'4.3.5']
arr.sort((a, b) = > {
const arr1 = a.split('. ');
const arr2 = b.split('. ');
let i = 0;
while (true) {let str1 = arr1[i];
let str2 = arr2[i];
i++;
if(str1===undefined||str2===undefined) {return arr1.length-arr2.length
}
if(str1===str2) continue;
return parseInt(str1)-parseInt(str2); }});console.log(arr);/ / / ', 'while', 'while', '0.1.1.1', '2.2', '4.3.5]
Copy the code
8. LRU (least recently used) algorithm
First take you know LRU:blog.csdn.net/belongtocod…
// A special stack can be used to hold the individual private keys currently in use.
// When a new private key is added, it is pushed to the top of the stack, and other private keys are moved to the bottom of the stack. If memory is insufficient, the page number at the bottom of the stack is removed.
// In this way, the top of the stack is always the most recently accessed private key, and the bottom is the most recently unaccessed private key.
// Implement an LRU (least recently used) caching mechanism
// Support get (key) to obtain data, push (key,value) to write data
class LRU{
constructor(capacity) {
this.capacity = capacity;// Set the cache capacity
this.secrets = new Map(a);// Store keys and key values
}
get(secretKey){
if(this.secrets.has(secretKey)){
let secretValue = this.secrets.get(secretKey)
this.secrets.delete(secretKey);// Delete the key and add it to the top of the stack
this.secrets.set(secretKey,secretValue);
return secretValue;
}else{
return -1; }}put(secretKey,secretValue){
// Check whether there is a key in the stack. If there is, delete it and add it to the top of the stack
if(this.secrets.get(secretKey)){
this.secrets.delete(secretKey);
this.secrets.set(secretKey,secretValue);
}else if(this.secrets.size < this.capacity){// Key does not exist. Capacity is not full
this.secrets.set(secretKey,secretValue);
}else{// The key does not exist. Capacity is full. Remove key from bottom of stack and add new key to top of stack
this.secrets.delete([...this.secrets.keys()][0]);
//this.secretKey.delete(this.secretKey.keys().next().value); / / same as above
this.secrets.set(secretKey,secretValue); }}}let cache = new LRU(2);
cache.put(1.'1');
cache.put(2.'2');
console.log(cache.get(1))/ / return '1'
cache.put(3.'3');// This operation invalidates key 2
console.log(cache.get(2))// return -1 (not found)
cache.put(4.'4');// This operation invalidates key 1
console.log(cache.get(1))// return -1 (not found)
console.log(cache.get(3))/ / return '3'
console.log(cache.get(4))/ / return '4'
Copy the code
9. Currize the function
function curry(fn,args){
const fnLen = fn.length;// The length of the entire function argument
args = args || [];
return function (){ // Return one function at a time
console.log(arguments)// The first function argument object - class array
let newArgs = args.concat(Array.prototype.slice.call(arguments))
if(newArgs.length<fnLen){
returncurry(fn,... newArgs);// If the length is insufficient, continue currization
}else{
return fn.call(this. newArgs);// If the length is sufficient, return the currified function directly}}}function add(a, b, c) {
return a + b + c;
}
let sum = curry(add);
// console.log(sum(2)(3)(4))
/ / the console. The log (sum (2 and 4))
/ / sum (2) (3, 4);
console.log(sum(2.3) (4))
Copy the code
Dom tree to JSON object and DOM traversal
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="header">
<div class="content1">111</div>
<div class="content2">222</div>
<div class="content3">333</div>
</div>
<div id="main">
<div class="content4">
<span>The content of 1</span>
<span>Content of the 2</span>
<span>The content of 3</span>
</div>
</div>
<div id="footer">
<ul class="list">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
</body>
<script>
window.onload = function (){
let root = document.getElementsByTagName('body') [0];
if(root.length) return [];
// dom tree to JSON
// function dom2json(root){
// let obj = {};
// obj.name = root.tagName;
// console.log(root.tagName);
// obj.children = [];
// root.childNodes.forEach(child=>{
// if(child.tagName! ==undefined) {
// obj.children.push(dom2json(child))
/ /}
/ /})
// return obj
// }
// console.log(dom2json(root))
// Hierarchy traverses the DOM tree
let nodes = [];
let queue = [root];
console.log(root)
while (queue.length){
let levelLength = queue.length;
for(let i=0; i<levelLength; i++){const cur = queue.shift()
nodes.push(cur);
for(let item ofcur.children){ queue.push(item); }}}console.log(nodes)
}
</script>
</html>
Copy the code
11. Vdom (JSON object) to real DOM tree
let vdom = {
tag: 'DIV'.attrs: {
id: 'app'
},
children: [{tag: 'SPAN'.children: [{tag: 'A'.children: []}]}, {tag: 'SPAN'.children: [{tag: 'A'.children: []},
{tag: 'A'.children<div id= <div id= <div id= <div id="app">
<span>
<a></a>
</span>
<span>
<a></a>
<a></a>
</span>
</div>
Copy the code
function myRender(vdom) {
let dom = document.createElement(vdom.tag);
// Set the attributes on the tag
vdom.attrs&&Object.keys(vdom.attrs).forEach(key= >{
dom.setAttribute(key,vdom.attrs[key]);
})
// Add and render all child nodes recursively
vdom.children&&vdom.children.forEach(child= >{
dom.appendChild(myRender(child));
})
return dom;
}
//let el = document.getElementsByTagName('body')[0].appendChild(myRender(vdom))
console.log(myRender(vdom));
Copy the code
12, Implement the parent-child relationship array to JSON(V-DOM)
let arr = [{
id: 'id1'.parentId: ' '.children:[]
}, {
id: 'id2'.parentId: 'id1'.children:[]
}, {
id: 'id3'.parentId: 'id1'.children:[]
}, {
id: 'id4'.parentId: 'id1'.children:[]
}, {
id: 'id5'.parentId: 'id2'.children:[]
}, {
id: 'id6'.parentId: 'id3'.children:[]
}, {
id: 'id7'.parentId: 'id3'.children:[]
}, {
id: 'id8'.parentId: 'id4'.children:[]}] Results are:let res = {
"id": "id1"."parentId": ""."children": [{"id": "id2"."parentId": "id1"."children": [{"id": "id5"."parentId": "id2"."children": []}]}, {"id": "id3"."parentId": "id1"."children": [{"id": "id6"."parentId": "id3"."children": []}, {"id": "id7"."parentId": "id3"."children": []}]}, {"id": "id4"."parentId": "id1"."children": [{"id": "id8"."parentId": "id4"."children": []}]}Copy the code
function array2json(arr) {
let obj = {}
arr.forEach(item= > {
if (item.parentId === ' ') { obj = item; }})function dfs(obj) {
// Find all children
let childs = arr.filter(item= > {
returnitem.parentId === obj.id; }) obj.children.push(... childs)for (let child of childs) {// Iterate over all the child nodes
dfs(child);// DFS on the child node again as the current node
}
}
dfs(obj);
return obj;
}
console.log(array2json(arr))
Copy the code
13, according to the parent-child relationship to achieve JSON(V-DOM) to array
function json2array(res){
let arr = []
const dfs = function(obj){
for(let child of obj.children){
dfs(child);
}
obj.children = [];
arr.push(obj);
}
dfs(res);
return arr
}
console.log(json2array(res))
Copy the code
Implement Object.is
Object.is does not convert the type of the two values being compared, much like ===, although there are some differences.
- NaN is not equal in ===, but equal in object.is
- +0 and -0 are equal in ===, but not in object. is
Object.is = function (x, y) {
if (x === y) {
// In the current case, only one case is special: + 0-0
// If x! == 0, returns true
Infinity Infinity Infinity Infinity Infinity Infinity Infinity Infinity Infinity Infinity Infinity Infinity Infinity Infinity Infinity Infinity
returnx ! = =0 || 1 / x === 1 / y;
}
// x ! In the case of == y, we just need to determine if it is NaN, if x! If ==x, then x is NaN, and likewise y
// Return true if x and y are both NaN
returnx ! == x && y ! == y; };Copy the code
Implement AJAX requests
function getJSON(url){
return new Promise((resolve,reject) = >{
// Create an XHR object
let xhr = new XMLHttpRequest();
// Call the open method to set the basic request information
xhr.open('get',url,false)/ / false said async
// Set the request header information
xhr.setRequestHeader("Content-Type"."application/json")
// Register the listener function
xhr.onreadystatechange = function (){
if(xhr.readyState ! = =4) return;// The response is not complete
if(xhr.status === 200 || xhr.status === 304){
resolve(xhr.responseText) // Returns the response result
}else{
reject(new Error(xhr.responseText)) } } xhr.send(); })}Copy the code
16. Add large numbers
function add(a,b){
// Take the maximum length of the two numbers and complement them with 0
let maxLen = Math.max(a.length,b.length);
a = a.padStart(maxLen,'0')
b = b.padStart(maxLen,'0');
// Define the carry
let flag = 0;
let sum = ""
for(let i=maxLen-1; i>=0; i--){let temp = parseInt(a[i])+parseInt(b[i])+flag;
flag = Math.floor(temp/10);
sum = temp%10 + sum
}
return sum;
}
// Add large numbers
let a = "9007199254740991";
let b = "1234567899999999999";
console.log(add(a,b));
Copy the code
17. Array flattening
Conventional methods
function flatten(arr){
if(!Array.isArray(arr)){
throw new TypeError('args must be an array');
}
let res = [];
arr.forEach(item= > {
if(Array.isArray(item)){ res.push(... flatten(item));/ / minimum layer array, the need to expand and push into res -,2,2,4 [1] - [2, 4],1,2,2,4 [1]
}else{ res.push(item); }})return res;
}
console.log(flatten([1[1.2[2.4]],3.5])); // [1, 1, 2, 2, 4, 3, 5]
Copy the code
The Reduce method flattens
let arr = [1.2.'3js'[4.5[6], [7.8[9.10.11].null.'abc'] and {age: 58}].'[]'.null];
function flatten(arr) {
if(!Array.isArray(arr)){
throw new TypeError('not an array');
}
return arr.reduce((prev, cur) = > {
return Array.isArray(cur) ? prev.concat(flatten(cur)) : prev.concat(cur)
}, [])
}
console.log(flatten(arr))
Copy the code
18. Implement Reduce
Reduce the use of
var arr = [1.2.3.4];
var sum = arr.reduce(function(pre, cur, curIndex, arr) {
// pre returns the value of the last callback, cur current index value, curIndex current index value
console.log(pre, cur, curIndex);
return pre + cur;
},0) // The initial value passed to the function. The default is 0
console.log(sum);
Copy the code
Reduce implementation
// Example: arr.reduce(cb,initValue)
// 1. What are the parameters cb and initValue in the function
// 2. Callback function parameters (pre: cumulative value, cur: current value, curIndex: number, arr array that calls reduce)
// 3. Returns the pre accumulative value
Array.prototype.myReduce = function (cb,initValue){
// Check whether arr is an array
if(!Array.isArray(this)) {throw new TypeError('not a array')}let arr = this;
// If there is no initial value, default is 0
initValue = initValue || 0;
let pre = initValue;
// Cb returns a new pre after each execution, overwriting the previous one
arr.forEach((cur,curIndex) = >{
pre = cb(pre,cur,curIndex,arr)
})
return pre;
}
Copy the code
Reduce implementation map
// Example: arr.map(cb)
// 1. What argument cb is in the function
// 2. Callback arguments (cur: current value, curIndex: number of rows, arr: array traversed)
// The three arguments correspond to arguments 2, 3, and 4 of the callback received by the reduce function
// Take the elements of each iteration as arguments to the function passed in, and put the result of each iteration into a new array
Array.prototype.myMap = function (cb){
// Check whether arr is an array
if(!Array.isArray(this)) {throw new TypeError('not an array')}// Returns the final result after manipulating the array
return this.reduce((pre,cur,index,arr) = >{
pre.push(cb(cur,index,arr));
returnpre; }}, [])console.log([1.3.4].myMap((item) = >{
return item*2;
}))
Copy the code
Reduce implementation filter
// Example: arr.filter(cb)
// 1. What argument cb is in the function
// 2. Callback arguments (cur: current value, curIndex: number of rows, arr: array traversed)
// 3. The three arguments correspond to the second, third, and fourth arguments of the callback received by the reduce function
// Add the current value to the new array using the result true or false
Array.prototype.myFilter = function (cb){
// Check whether arr is an array
if(!Array.isArray(this)) {throw new TypeError('not an array')}// Returns the final result after manipulating the array
return this.reduce((pre,cur,index,arr) = >{
if(cb(cur,index,arr)){
pre.push(cur)
}
returnpre; }}, [])console.log([1.3.4].myFilter((item) = >{
return item===3;
}))
Copy the code
Reduce implements array deduplication
let arr = [1.2.3.1.1.2.3.3.4.3.4.5]
let result = arr.reduce((pre, item, index, arr) = > {
/ /! pre.includes(item) && pre.push(item);
if(! pre.includes(item)){ pre.push(item); }return pre;
}, [])
console.log(result); //[1, 2, 3, 4, 5]
// Other ways to undo (set+ deconstruct + expand operator)
let result = [...new Set(arr)]
Copy the code
Reduce achieves the maximum and minimum value of an array
let arr = [1.2.3.4.5.6.7]
console.log(arr.reduce((prev, cur) = >{
return Math.max(prev, cur)
})); / / 7
console.log(arr.reduce((prev, cur) = >{
return Math.min(prev, cur)
})); / / 1
Copy the code
19. Flat objects
Effect:
const obj = {
a: {
b: 1.c: 2.d: {e: 5}},b: [1.3, {a: 2.b: 3}].c: 3} The result is as follows/ / {
// 'a.b': 1,
// 'a.c': 2,
// 'a.d.e': 5,
// 'b[0]': 1,
// 'b[1]': 3,
// 'b[2].a': 2,
// 'b[2].b': 3
// c: 3
// }
Copy the code
function flatten(obj){
let res = {};
const dfs = function (preStr,cur){
// 2. Termination condition: the current value cur is neither an object nor an array
if(cur.constructor === Array) {// String when processing arrays, recursively
cur.forEach((item,index) = >{
dfs(`${preStr}[${index}] `, item); })}else if(cur.constructor === Object) {// Handle object strings recursively
Object.keys(cur).forEach(key= >{
PreStr =''; // If preStr='';
dfs(`${preStr}${preStr?'. ':' '}${key}`, cur[key])
})
}else{ res[preStr] = cur; }}// 1. Parameters to be passed for recursion: preStr: string of key, obj: value of current key
dfs(' ',obj);
return res;
}
console.log(flatten(obj))
Copy the code
Combination of deconstruction and expansion operators
// Implement string to array
let str ='abcdefg'
console.log([...str])
console.log(Array.prototype.slice.call(str))
console.log(str.split(' '))
// Other tips
let arr = [1.2.3.4]; // Array of classes
const [a,...arr1] = arr
console.log(a,arr1) //1 [2, 3, 4]
Copy the code
21. Implement setTimeout=>setInterval
Function mySetInterval(cb,delay){let timeId = null; const dfs = function (){ cb(); SetTimeout (()=>{DFS ()},delay)} TimeId = setTimeout(()=>{DFS ()},delay) return timeId; } let timeId = mySetInterval(()=>{console.log('a')},1000) console.log(timeId) // numberCopy the code
/ / the full version
let timeMap = {}
let id = 0 // Simply implement unique id
const mySetInterval = (cb, time) = > {
let timeId = id // Assign timeId to id
id++ // id Specifies a unique ID
let fn = () = > {
cb()
timeMap[timeId] = setTimeout(() = > {
fn()
}, time)
}
timeMap[timeId] = setTimeout(fn, time)
return timeId / / return timeId is
}
let id2 = mySetInterval(() = >{
console.log('A hundred million a second');
},1000)
// console.log(id) //Number Number
const myClearInterval = (id) = > {
clearTimeout(timeMap[id]); // Run timeMap[id] to get the real ID
delete timeMap[id];
}
setTimeout(() = >{
myClearInterval(id2);
},3000)
Copy the code
Little knowledge:
1. This in the setTimeout callback refers to the window. If you want to use this, there are two ways:
- The callback uses the arrow function so that this points to the outer layer
- The way variables are set externally
2. Js timer output time is not accurate
setInterval(() = >{
console.log('data:' + new Date());
},1000)
// Because js is single threaded, to execute the code, you need to put the task queue to wait for execution
setTimeoutThe second argument to () tells JavaScript how long to add the current task to the queue. If the queue is empty, the added code executes immediately; If the queue is not empty, it will wait until the previous code has finished executingCopy the code
function test(){
this.name = 'hzy';
setTimeout(function (){
console.log(this) //window
},1000)}// use the arrow function
function test(){
this.name = 'hzy';
setTimeout(() = >{
console.log(this) //test { name: 'hzy' }
},1000)}// Set variables
function test(){
this.name = 'hzy';
let self = this;
setTimeout(function (){
console.log(self) //test { name: 'hzy' }
},1000)}new test()
Copy the code
22, function anti-shock (debounce)
The callback is executed n seconds after the event is triggered, and if it is triggered again within n seconds, the timer is reset.
- When using Echarts to change the browser width, you want to rerender (anti-shake can replace resize)
- Typical case: When typing a search, because data is requested asynchronously from the back end through input, leaving it untreated causes bugs
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0, the maximum - scale = 1.0, user - scalable = no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Image stabilization</title>
</head>
<body>
<button id="debounce">Tap me!</button>
<script>
window.onload = function() {
// 1. Get the button and bind the event
var myDebounce = document.getElementById("debounce");
myDebounce.addEventListener("click", debounce(sayDebounce));
}
// 2. Function of anti-shake function, accept parameter transfer
function debounce(fn) {
// create a flag to store the return value of the timer
let timeout = null;
return function() {/ / closures timeout
// Every time the user clicks/input, the previous timer is cleared
clearTimeout(timeout);
// create a new setTimeout.
// This ensures that the button is clicked within the interval
// If the user still clicks, the fn function will not be executed
timeout = setTimeout(() = > {
fn.call(this.arguments);
}, 1000);
};
}
// 3. Need to handle the event of shaking prevention
function sayDebounce() {
/ /... Some of the work that needs to be done is done here
console.log("Quaking succeeded!");
}
</script>
</body>
</html>
Copy the code
23. Function throttle
Specifies that a function can fire only once per unit of time. If more than one function is fired in this unit of time, only one function will take effect.
Remember: Function throttling is the rate of fire in an FPS game, even if you hold down the mouse to shoot, the bullet will only be fired within the specified rate of fire
function throttle(fn,delay) {
// Save a tag through a closure
let canRun = true;
return function() {
// Check whether the flag is true at the beginning of the function, or break the function if it is not
if(! canRun) {return;
}
// Set canRun to false to prevent it from being executed before it is executed
canRun = false;
setTimeout( () = > {
fn.call(this.arguments);
// After executing the event (such as calling the interface), reset the flag to true
canRun = true;
}, delay);
};
}
Copy the code
24, the use of set intersection, union, difference set
// implement union, intersection, difference set
let a =[1.2.2.3.4.2];
let b =[2.3.3.4.5];
let union =new Set([...a, ...b]);
console.log(union);/ / and set
// set,map has no filter method
let intersect =new Set(a.filter(item= > new Set(b).has(item)));
console.log(intersect);/ / intersection
// Difference set = union - intersection
let difference = [...union].filter(item= >! intersect.has(item))console.log(difference)
Copy the code
25. Advanced filtering map+filter
// Required: names over 18 years old
let arrObj = [{
name: 'aa'.age: 13
}, {
name: 'bb'.age: 23
}, {
name: 'cc'.age: 18
}, {
name: 'dd'.age: 11
}, {
name: 'ee'.age: 28
}]
let arrObjFilter = arrObj.filter(ele= > {
return ele.age > 18;
}).map(ele= >{
return ele.name;
})
console.log(arrObjFilter) // ['bb', 'ee']
Copy the code
26. Realize the function combination operation compose
// Use:
function fn1(x) {
return x + 1;
}
function fn2(x) {
return x + 2;
}
function fn3(x) {
return x + 3;
}
function fn4(x) {
return x + 4;
}
const a = compose(fn1,fn2,fn3,fn4);
console.log(a(1));// equivalent to fn1(fn2(fn3(fn4(1))))
/ / 1 + 4 + 3 + 2 + 1 = 11
Copy the code
function compose(... fns){ if(fns.length===0) { return function (... args){ return args; } } return fns.reduce((pre,cur)=>{ return function (... args1){ return pre(cur(... args1)) } }) }Copy the code
27, URL-related operations
Matching parameter values
(^ | &)
This matches either empty or ampersand strings, for example, “AD” or “& AD”([^ &] *)
This means that you cannot start with zero or more ampersands(& | $)
It is followed by an ampersand or a null-ending string, such as “& AD “or” AD “.
const url = 'http://www.xxxxxxx.cn/?lx=1&name=JS&from=baidu&name=2#video'
let key = 'name'
const reg = new RegExp("(^ | &)"+key+"= (/ ^ & *) (& | $)");
console.log(url.split('? ') [1].split(The '#') [0].match(reg)[2])
Copy the code
Store parameter key values
const url = 'http://www.xxxxxxx.cn/?lx=1&name=JS&from=baidu#video'
let params = new Map(a)let paramList = url.split('? ') [1].split(The '#') [0].split('&');
paramList.forEach(item= > {
let key = item.split('=') [0]
let value = item.split('=') [1];
params.set(key,value);
})
console.log(params)
// Map(3) { 'lx' => '1', 'name' => 'JS', 'from' => 'baidu' }
Copy the code
28, implement range
// implement the effect
const range = new Range(3.8);
// Complete the iteration once
for (const num of range){
console.log(num);/ / 3,4,5,6,7
}
// Drop out
for (const num of range){
if(num>5) {break; // Automatically call the return method
}
console.log(num);/ / three, four, five
}
Copy the code
The iterator implementation range
// Define a range of prematurely terminated iterators
class Range{
constructor(start,end) {
this.start = start;
this.end = end;
}
// for.. By default, of calls iterator, returning one value per iteration
[Symbol.iterator](){
let left = this.start;
let end = this.end;
return {
next(){
if(left<end){
return {done:false.value:left++}
}else{
return {done: true}}},// This is a return() method, not the return keyword
return() {
console.log('Early exit')
return {done:true}
}
}
}
}
Copy the code
The generator to achieve the range
function* myRange(start, end) {
while (start < end) {
yieldstart++; }}const range = myRange(3.9);
console.log(range[Symbol.iterator]() === range);//true
for (const num of range) {
console.log(num);//3 4 5 6 7 8
}
Copy the code
Sharding idea of big data rendering
When rendering millions of large data with simple structure, the sharding idea is used to optimize rendering ——- recursion
// Insert the li label into ul
let ul = document.getElementsByTagName("body") [0];
// Insert 100,000 pieces of data
let total = 1000;
// Insert 20 strips at a time
let once = 20;
// Index of records per page
let index = 0;
function loop(curTotal,curIndex){
if(curTotal<=0) {// Everything is rendered
return false;
}else if(curTotal<once){// Once =20
once = curTotal;
}
for(let i=0; i<once; i++){let li = document.createElement("li");
li.innerHTML = The first `${curIndex+i}The data `;
ul.appendChild(li);
}
loop(curTotal-once,curIndex+once)
}
loop(total,index)
Copy the code
Regular expressions
Vue template variable replacement
let template = 'I am {{name}}, age {{age}}, gender {{sex}}';
let data = {
name: 'name'.age: 18
}
console.log(render(template, data));
// I am name, age 18, gender undefinedSolution a:function render(template,data){
const reg = /{{(\w+)}}/;
// If {{}} does not exist, return to template
if(reg.test(template)){
// Find the first template string field in the current template
const name = template.match(reg)[1];
template = template.replace(reg, data[name]);
// If you render for the first time, you will return the template
return render(template,data);
}
returntemplate; } Replace is very powerful and can implement multiple simultaneous substitutionsfunction render(template,data){
const reg = /{{(\w+)}}/g;
return template.replace(reg, function (item){
// console.log(item.slice(2,-2)) cuts the string between the second index and the penultimate index
return data[item.slice(2, -2)]; })}Copy the code
hump
let str = "next-to-meet-you"
console.log(hump(str))
// nextToMeetYou
function hump(str){/ / hump
const reg = /-\w/g;
return str.replace(reg, function (item){
return item.slice(1).toUpperCase()
})
}
Copy the code
Commonly used regular
// Replace date '2015-12-25' with '12/25/2015'
let date = '2015-12-25'
let reg = /(\d{4})-(\d{2})-(\d{2})/g
console.log(date.replace(reg,'$1 / $2 / $3'))
// Phone number
const reg = /^1[34578]\d{9}$/
// Verify the mailbox
[email protected]
18843186666@163.com
const reg = /^([a-zA-Z0-9_\-])+@([a-zA-Z0-9_\-])+(\.[a-zA-Z0-9_\-])+$/
// Province certificate numberThe first generation id card is15Bit code The number of China's second-generation resident identity card is18positionconst reg = /(^\d{15}$)|(^\d{17}[\dxX]$)/
Copy the code
conclusion
Feel good writing, helpful to you, you can share with people around you, the more you share knowledge, do not be stingy
Follow-up update vUE underlying related principles, please pay attention to me, tidy up, share with you, we learn the front end together