1. Array correlation
1-1, generate a sequential array from 1 to n and scramble the order
function creNumArr(n) {
let arr = [], i = 0;
while (i < n) {
arr.push(++i)
}
return arr.sort(() = > Math.random() > 0.5 ? 1 : -1);
};
Copy the code
1-2. Generate an array of length N with values ranging from 1 to Max
function creNumArr2(n, max) {
return Array.from(
{ length: n },
v= > parseInt((Math.random() * max).toFixed())
)
}
Copy the code
or
function creNumArr2(n, max) {
return [...new Array(n)].map(v= > parseInt((Math.random() * max).toFixed()))
}
Copy the code
Note that new Array(10) creates a sparse Array and has no effect on sparse Array map, filter, forEach, etc. Such as
let a = new Array(10).map(v= > 1);
console.log(a[0]);//undefined
Copy the code
1-3. Count the number of occurrences of each element in the array
let b = creNumArr2(5.100); // The length is 5 and the values are from 1 to 100
let c = b.reduce((result, v) = > {
if (result.has(v)) {
let _d = result.get(v);
result.set(v, ++_d);
} else {
result.set(v, 1);
}
return result;
}, new Map());
console.log(c);
Copy the code
1-4. Array deduplication
The es6 method uses the uniqueness of Set values
Array.from(new Set(arr));
[...new Set(arr)];// Or use the extension operator
Copy the code
The method of es5
a.filter((v, i, arr) = > arr.indexOf(v) === i);
Copy the code
1-5. Find the union of two arrays
let a = new Set([1.2.3])
let b = new Set([4.3.2])
let union = new Set([...a, ...b])
Copy the code
1-6. Class arrays are converted to arrays
Es6 method
const arr = [...fakeArray];
const arr2 = Array.from(fakeArray);/ / or
Copy the code
Es5 method
const arr = Array.prototype.slice.call(fakeArray)
Copy the code
1-7. Array flattening
Concept: converting a [1,2,[3,[4,5]] array to the form [1,2,3,4,5] is flattening.
The use of flat
const newArr = arr.flat(Infinity)
Copy the code
Using a recursive
const flatArr = function f(arr) {
const newArr = [],
len = arr.length;
for(let i =0; i<len; i++){if(Array.isArray(arr[i])){ newArr.push(... f(arr[i])); }else{ newArr.push(arr[i]); }}return newArr;
}
Copy the code
Use a while loop
const flatArr = arr= > {
while(arr.some(v= > Array.isArray(v))){ arr = [].concat(... arr);// The key is that if contact is an array, then the element in the array is added, not the array}}Copy the code
1-8. Concatenate 4 random values from the array into a string
const arr = [1.3.'t'.'i'.'o'.9].sort(() = > Math.random() > 0.5 ? 1 : -1);
const str = arr.join(' ').slice(0.4);
console.log(str);
Copy the code
2. Some simple algorithms
2-1. Bubble sort
function bubbleSort(arr) {
let _len = arr.length;
for (let i = 0; i < _len; i++) {
for (let j = 0; j < _len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
}
}
}
}
Copy the code
2-2. Selection sort
function selectAort(arr) {
let _len = arr.length;
for (let i = 0; i < _len; i++) {
let min = i;
for (let j = i + 1; j < _len; j++) {
if(arr[j] < arr[min]) { min = j; }}if(min ! == i) { [arr[min], arr[i]] = [arr[i], arr[min]]; }}}Copy the code
2-3. Quicksort
const quikcSort = function f(arr) {
const _len = arr.length;
if (_len <= 1) {
return arr;
} else {
let leftArr = [], rightArr = [];
for (let i = 1; i < _len; i++) {
if (arr[i] > arr[0]) {
rightArr.push(arr[i])
} else {
leftArr.push(arr[i])
}
}
return [...f(leftArr), arr[0], ...f(rightArr)]
}
}
Copy the code
3. Function correlation
3-1. Function shake proof
The callback is executed n seconds after the event is triggered, and if it is triggered again within n seconds, the timer is reset. Main applications:
- Search search lenovo, the user in the continuous input value, with anti – shake to save the request resources;
- Windows triggers resize. Resize the browser window repeatedly to trigger resize. Use stabilization to make it trigger only once
function debounce(fn, wait = 500) {
let timer;
return function() {
timer && clearTimeout(timer);
timer = setTimeout(() = > {
fn.apply(this.arguments)
}, wait)
}
}
Copy the code
3-2. Function throttling
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. Main applications:
- Click the mouse repeatedly to trigger the mousedown(trigger only once in unit time);
- Listen for rolling events, such as whether to slide to the bottom to automatically load more, and throttle
function throttle(fn, wait = 500) {
let prev = Date.now();
return function() {
const now = Date.now();
if (now - prev > wait) {
fn.apply(this.arguments);
prev = Date.now(); }}}Copy the code
3-3. Currization and anti-Currization of functions
The rewriting of F (1,2,3) into f(1), (2), and (3) is called currization. Conversely, rewriting f(1), (2), and (3) into f(1,2,3) is called anti-Cremation.
const curry = fn= > {
const judge = (. args) = > {
if (args.length === fn.length){
returnfn(... args); }return (. arg) = >judge(... args, ... arg); }return judge;
}
Copy the code
3-4. Partial functions
A partial function is a new function that takes a function with multiple arguments, fixes some of the arguments, and passes in the rest as arguments. Partial functions and function Corrification are both applications of closures.
const partial = (fn, ... args) = > {
return (. arg) = > {
returnfn(... args, ... arg); }; }Copy the code
3-5. Trampoline function
The trampoline function is designed to solve the stack overflow problem of recursive functions by using a while loop to change the recursion into an iterative loop. It’s understandable that trading space for time is slower than normal recursion, but slow is better than overflow.
//Uncaught RangeError: Maximum Call stack size exceeded The call stack overflow, or a large number of recursive calls will occur.
Stack overflow (function call stack)
- Tail-call optimization is used, but only in strict mode.
- The trampoline function is essentially recursive in the form of an iterative loop.
If you want to implement a sum from 1 to 100, the normal recursion is:
const add = function f(v) {
if (v < 1) {
return v;
} else {
return v + f(v - 1); }}Copy the code
Tail-call optimization is of the form:
const add = function f(v, m = 0) {
if(v === 1) {return v+m;
}else{
return f(null, v-1, v + m); }}Copy the code
The trampoline function is:
// The trampoline function
const trampoline = f= > (. args) = > {
letresult = f(... args);while (typeof result === 'function') {
result = result();
}
return result;
}
const add = function f(v, m = 0) {
if(v === 1) {return v+m;
}else{
return f.bind(null, v-1, v + m);
// Use bind to return a new function}}const add2 = trampoline(add);// Use the trampoline function to get an iterative function
Copy the code
4, Call, apply, bind
4-1. Call implementation
Function.prototype.myCall = function(asThis, ... arg) {
if (asThis === undefined || asThis === null) {
asThis = window;
} else {
asThis = new Object(asThis);
}
let FN = Symbol('FN');
asThis[FN] = this;
letresult = asThis[FN](... arg);delete asThis[FN];
return result;
}
Copy the code
4-1. Implement BIND
Function.prototype.myBind = function(asThis, ... arg) {
let _this = this;
if (typeof_this ! = ='function') {
throw new Error('not a function');
}
let newFn = function() {
return _this.apply(
newFn.prototype.isPrototypeOf(this)?this : asThis,
[...arg, ...arguments]
)
}
newFn.prototype = _this.prototype;
return newFn;
}
Copy the code
And you see it all the time
var fNOP = function () {};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
Copy the code
Thought it was to prevent prototype chain tampering. However, there are differences between this mock implementation of BIND and the standard BIND, see this article for a personal understanding of the return value of bind
Shallow copy and deep copy
5-1. Concept differentiation
Assignment:
- When we copy a variable of a reference type, we are actually copying the address stored in the stack. Creating a reference to an object’s address is assignment.
Shallow copy
- Creates a new object with an exact copy of the original object property values. If the property is a primitive type, it copies the value of the primitive type, and if the property is a reference type, it copies the memory address, so if one object changes the address, it affects the other object.
- The copy of an object instance by an extension operator is a shallow copy
Deep copy
- To make a complete copy of an object out of memory, a new area of heap memory is created to hold the new object, and modification of the new object does not affect the original object
A circular reference
- That is, an object’s attributes refer indirectly or directly to itself.
- Solve the problem of circular reference, we can create a extra storage space, to store the current objects and copy the object correspondence, when need to copy the current object, go to the storage space, find ever copy this object, if any direct return, if not to copy, so clever resolve problem of circular references. This storage space needs to be able to store key-value data, and the key can be a reference type, we can choose Map data structure.
JSON.parse(JSON.stringify(a))
An error is reported when handling duplicate references
5-2. Shallow copy
function shallowCopy(target) {
let cloneTarget = {};
for (const key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) { cloneTarget[key] = target[key]; }}return cloneTarget;
};
Copy the code
5-3. Deep copy
5-3-1. Beggar’s Edition
JSON.parse(JSON.stringify(a));
Copy the code
Disadvantages:
- Undefined (null) is not supported.
- Circular references are not supported and an error will be reported
- If Date is not supported, it will be a string in ISO8601 format. Regular expressions are not supported
- Unsupported functions
5-3-2, support arrays, common objects, resolve repeated reference
function clone(target, map = new WeakMap(a)) {
if (typeof target === 'object') {
let cloneTarget = Array.isArray(target) ? [] : {};
if (map.has(target)) {
return map.get(target);
}
map.set(target, cloneTarget);
for (const key in target) {
// For in iterates through all enumerable attributes on the prototype chain
cloneTarget[key] = clone(target[key], map);
}
return cloneTarget;
} else {
returntarget; }};Copy the code
5-3-3, support Date, RegExp, Error type
function deepClone(o, map = new WeakMap(a)) {
if (o && typeof o === 'object') {
let typeArr = ['[object Object]'.'[object Array]'.'[object Date]'.'[object RegExp]'.'[object Error]'.'[object Set]'.'[object Map]'],
t = Object.prototype.toString.call(o);
if (~typeArr.indexOf(t)) {
if (map.has(o)) {
return map.get(o); // Prevent circular references
}
let tempObj = new o.__proto__.constructor();
map.set(o, tempObj);// The contents of tempObj will be modified later. Here is a reference
// if map.set(o, o); It will reference itself, it will make an error
if (t === '[object Date]') {
return new Date(o); / / Date type
}
if (t === '[object RegExp]') {
return new RegExp(o); / / the RegExp type
}
if (t === '[object Error]') {
return new Error(o); / / the Error types
}
if (t === '[object Set]') {
/ / Set type
o.forEach(v= > {
tempObj.add(deepClone(v, map));
});
return tempObj;
}
if (t === '[object Map]') {
/ / Map types
o.forEach(v= > {
tempObj.set(deepClone(v, map));
});
return tempObj;
}
// Arrays, ordinary objects, and other types
for (let key in o) {
if (Object.prototype.hasOwnProperty.call(o, key)) { tempObj[key] = deepClone(o[key], map); }}return tempObj;
} else {
return o;// If it is any other type, return it directly}}else {
return o;Function, NULL, and primitive type values are returned directly}}Copy the code
Functions do not need to be copied, and there is no problem with two objects using a function at the same address in memory. If you must copy a function, you can use eval.
The 5-3-4while loop unfolds
All recursion forms can be expanded into an iterative loop using while. This avoids possible recursive stack burst problems. But the execution will be slower. Understood as space for time
Deep copy with MessageChannel
let obj = {
a: 1.b: {
c: 2.d: 3,},f: undefined
}
obj.c = obj.b;
obj.e = obj.a
obj.b.c = obj.c
obj.b.d = obj.b
obj.b.e = obj.b.c
function deepCopy(obj) {
return new Promise((resolve) = > {
const { port1, port2 } = new MessageChannel();
port2.onmessage = ev= > resolve(ev.data);
port1.postMessage(obj);
});
}
deepCopy(obj).then((copy) = > { // Remember that 'MessageChannel' is asynchronous!
let copyObj = copy;
console.log(copyObj, obj)
});
Copy the code
- MessageChannel copy works in the same way as postMessage of Web workers
- I can copy undefined,
- Can solve circular reference,
- Is asynchronous
Deep copy of 5-3-6 special examples
If it is an array where all elements are primitive data types, you can do as follows
let a = [1.7.8.2.0];
let b = a.slice();/ / shallow copy
let c = [...a];/ / shallow copy
Copy the code
If it is an object whose values are all basic data types, you can perform the following operations
let a = { aa: 1, bb: 2 } let b = Object.assign({}, a); // let c = {... a}; / / shallow copyCopy the code
6. New operation
6-1. Process of new operation
To create an instance of Person, use the new operator. Calling the constructor in this way does the following.
- Create a new object in memory.
- Inside this new object
[[Prototype]]
Property is assigned to the constructor’s Prototype property. - This inside the constructor is assigned to the new object (that is, this refers to the new object).
- Executes the code inside the constructor (adding attributes to the new object).
- If the constructor is a complex data type (or reference type), return that object. Otherwise, the newly created object is returned.
6-2. Handwritten implementation
function myNew() {
// arguments ()
const Con = Array.prototype.shift.call(arguments);
// create an empty object and link it to the prototype
const obj = {};
Object.setPrototypeOf(obj, Con.prototype);
// pbj.__proto__ = con. prototype; // But this is less efficient
//或者const obj = Object.create(Con.prototype);
// obj can access the properties in the constructor
const res = Con.apply(obj, arguments)
// return the object returned by the constructor first
return res instanceof Object ? res : obj;
}
Copy the code
The __proto__ attribute was only standardized in ES6 to ensure Web browser compatibility, but is not recommended for performance reasons other than standardization. For better support, object.getProtoTypeof () is recommended.
- Of the object
[[Prototype]]
It is recommended to useObject.getPrototypeOf()
orReflect.getPrototypeOf()
; - Of the set object
[[Prototype]]
It is recommended to useObject.setPrototypeOf()
orReflect.setPrototypeOf()
;
Implement an instanceof
Compares whether the object’s __proto__ and the target’s prototype are equal, and if not, looks up the prototype chain for a match.
const myInstanceof = (o1, o2) = > {
let proto = o1.__proto__;
while(proto ! == o2.prototype){if(proto){
proto = proto.__proto__;
}else{
return false; }}return true;
}
Copy the code
8. Make simple promises
class myPromise {
constructor(executor) {
this.status = "pending"; // Default promise state
this.value; // Resolve specifies the successful value
this.resolveQueue = []; // Callback queue on success
const resolve = value= > {
if (this.status === "pending") {
this.value = value;
this.status = "fulfilled";
this.resolveQueue.forEach(fn= > fn())
}
}
executor(resolve);
}
then(onFullfilled) {
return new myPromise((resolve) = > {
setTimeout(() = > {/ / asynchronous
const res = onFullfilled(this.value);
if(res instanceof myPromise){
res.then(resolve)
}else{ resolve(res); }},0)}); }}Copy the code
9. Release the subscriber model
persistence