The following is a summary of pure dry handwritten version of the pen test code, do not thank you!
Promise variant
promise.first
The first returns a Promise of success
if (!Promise.first) {
Promise.first = (promiseList) = > {
return new Promise((resolve, reject) = > {
let rejectNum = 0;
const len = promiseList.length;
promiseList.forEach((pr) = > {
Promise.resolve(pr)
.then(resolve)
.catch(() = > {
rejectNum++; // Record the number of reject
if (rejectNum == len) {
reject("all promise is reject"); }}); }); }); }; }Copy the code
promise.last
The last one returns a Promise of success
if (!Promise.last) {
Promise.last = (promiseList) = > {
return new Promise((resolve, reject) = > {
let num = 0;
const len = promiseList.length;
let lastResult;
const fn = () = > {
if(num ! == len) {return;
}
lastResult ? resolve(lastResult) : reject("all promise is reject");
};
promiseList.forEach((pr) = > {
Promise.resolve(pr)
.then((data) = > {
lastResult = data;
num++;
fn();
})
.catch(() = > {
num++;
fn();
});
});
});
};
}
Copy the code
promise.none
In contrast to promise.all, when all promises are rejected, promise.None becomes complete
if (!Promise.none) {
Promise.none = (promiseList) = > {
return Promise.all(
promiseList.map((pr) = > {
return new Promise((resolve, reject) = > {
return Promise.resolve(pr).then(reject, resolve); }); })); }; }Copy the code
Promise.any
Only the results of all promises that enter the completed state are fetched, and those rejected are ignored
if (!Promise.any) {
Promise.any = (promiseList) = > {
return new Promise((resolve, reject) = > {
const result = [];
let num = 0;
const len = promiseList.length;
const fn = () = > {
if (num == len) {
result.length < 1 ? reject("all promise is reject") : resolve(result); }}; promiseList.forEach((pr) = > {
Promise.resolve(pr)
.then((data) = > {
result.push(data);
num++;
fn();
})
.catch(() = > {
num++;
fn();
});
});
});
};
}
Copy the code
Promise.every
Return true if all promises are completed, false otherwise
if (!Promise.every) {
Promise.every = (promiseList) = > {
return new Promise((resolve, reject) = > {
Promise.all(promiseList)
.then(() = > Promise.resolve(true))
.catch(() = > Promise.reject(false));
});
};
}
Copy the code
Promisify
The question
/ / before use
fs.readFile("./index.js".(err, data) = > {
if(! err) {console.log(data.toString());
}
console.log(err);
});
// after using promisify
const readFile = promisify(fs.readFile);
readFile("./index.js")
.then((data) = > {
console.log(data.toString());
})
.catch((err) = > {
console.log("error:", err);
});
Copy the code
solution
function promisify(fn) {
return (. args) = > {
return new Promise((resolve, reject) = > {
fn.apply(this, [
...args,
(err, data) = > {
if(! err) {return resolve(data);
}
returnreject(err); },]); }); }; }Copy the code
Sleep simulation
async function sleep(sleepTime) {
return new Promise((resolve) = > {
setTimeout(resolve, sleepTime);
});
}
Copy the code
JS implements an asynchronous scheduler with concurrency limits
The question
JS implements an asynchronous Scheduler Scheduler with concurrency limits, ensuring that up to 10 tasks can be run at the same time.
Class Scheduler{
constructor(max){}
run(callback){/ *... * /}}let s = new Scheduler(10);
s.run(async() = > {/* some async operations */
});
Copy the code
solution
Class Scheduler{
COUNT = 0;
LIST = [];
constructor(max){
this.LIMIT = 10;
}
async run(callback){
if(this.COUNT >= this.LIMIT){
// With await, as long as resolve is not done, the code execution will block here
await new Promise((resolve) = > {
this.list.push(resolve);
});
}
this.COUNT++;
const result = await callback();
this.COUNT--;
if(this.list.length > 0) {this.list.shift()(); // Unlock code is blocked
}
returnresult; }}let s = new Scheduler(10);
s.run(async() = > {/* some async operations */
});
s.run(async() = > {/* some async operations */
});
s.run(async() = > {/* some async operations */
});
Copy the code
Write a Promise
Key points of Promise
- A Promise is a class that takes an executor and executes it immediately
- Promises come in three states
- Pending waiting for
- Fulfilled complete
- The rejected failure
- The state can only change once, not backwards.
- pending -> fulfilled
- pending -> rejected
- Promise uses the resolve and reject functions to change the state
- Then method makes internal state judgment and executes corresponding method
- There are static methods promise.resolve and promise.reject
Handwritten edition
// State constant
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class Promise {
state = PENDING;
value = undefined;
reason = undefined;
onResolveCallback = [];
onRejectCallback = [];
constructor(executor) {
try {
executor(this.resolve, this.reject);
} catch (err) {
this.reject(err); }}resolve(data) {
if (this.state ! == PENDING) {return;
}
this.state = FULFILLED;
this.value = data;
while (this.onResolveCallback.length > 0) {
const currentResolve = this.onResolveCallback.shift();
currentResolve(this.value); }}reject(err) {
if (this.state ! == PENDING) {return;
}
this.state = REJECTED;
this.reason = err;
while (this.onRejectCallback.length > 0) {
const currentReject = this.onRejectCallback.shift();
currentReject(this.reason); }}static resolve(param) {
// Param is a Promise object that returns directly
if (param instanceof Promise) {
return param;
}
// Change to normal Promise
return new Promise((resolve) = > {
resolve(param);
});
}
static reject(reason) {
return new Promise((resolve, reject) = > {
reject(reason);
});
}
catch(fn) {
if (this.state == REJECTED) {
typeof fn == "function" && fn(this.reason); }}then(resolve, reject) {
const realResolve =
typeof resolve == "function" ? resolve : (value) = > value;
const realReject =
typeof reject == "function"
? reject
: (reason) = > {
throw reason;
};
// a chain call that returns a new Promise instance
const newPromise = new Promise((resolve, reject) = > {
// Create a microtask and wait for the Promise initialization to complete
const microResolve = () = > {
queueMicrotask(() = > {
try {
const x = realResolve(this.value);
resolvePromise(newPromise, x, resolve, reject);
} catch(err) { reject(err); }}); };const microReject = () = > {
queueMicrotask(() = > {
try {
const x = realReject(this.reason);
resolvePromise(newPromise, x, reasolve, reject);
} catch(err) { reject(err); }}); };if (this.state == FULFILLED) {
return microResolve(this.value);
}
if (this.state == REJECTED) {
return microReject(this.reason);
}
if (this.state == PENDING) {
this.onResolveCallback.push(microResolve);
this.onRejectCallback.push(microReject); }});returnnewPromise; }}function resolvePromise(newPromise, x, resolve, reject) {
if (newPromise == x) {
return reject(new Error("Circular reference"));
}
if (x instanceof Promise) {
x.then(resolve, reject);
} else{ resolve(x); }}Copy the code
Simulate the implementation of BIND
ES5 version
Function.prototype.bind =
Function.prototype.bind ||
function (context) {
if (typeof this! = ="function") {
throw new Error("can't bind");
}
let self = this;
let args = Array.prototype.slice(arguments.1); // Cache parameters
const fnOP = function () {};
const bound = function () {
let innerArgs = Array.prototype.slice(arguments);
return self.apply(
this instanceof fnOP ? this : context,
args.concat(innerArgs)
);
};
fnOP.prototype = this.prototype;
bound.prototype = new fnOP();
return bound;
};
Copy the code
ES6 version
Function.prototype.bind =
Function.prototype.bind ||
function () {
if (typeof this! = ="function") {
throw new Error("can't bind");
}
const args = Array.from(arguments);
const context = args.shift();
const self = this;
const fnOP = Object.create(this.prototype);
const fn = function () {
const innerArgs = Array.from(arguments);
return self.apply(
this instanceof fnOP ? this : context,
args.concat(innerArgs)
);
};
fn.prototype = fnOP;
return fn;
};
Copy the code
Simulate the implementation of new
function Otaku(name, age) {
this.name = name;
this.age = age;
this.habit = "Games";
}
Otaku.prototype.strength = 60;
Otaku.prototype.sayYourName = function () {
console.log("I am " + this.name);
};
/ / call
myNew(Otaku, "Kevin"."18");
console.log(person.name); // Kevin
console.log(person.habit); // Games
console.log(person.strength); / / 60
person.sayYourName(); // I am Kevin
Copy the code
/ / implementation
function myNew(fn, ... args) {
const obj = Object.create(fn.prototype);
const ret = fn.apply(obj, args); // Ret may be null
return typeof ret === "object" ? ret || obj : obj;
}
Copy the code
Deep copy
Deep copy note
- Note the types, the seven basic types:
boolean
,string
,number
,undefined
、null
,Symbol
,BigInt
Object
Types of possible Object. The prototype. ToString. (call) :- [object Object]
- [object Function] –
typeof function == function
- [object Null]
- [object Array]
- [object RegExp]
solution
function deepCopy(data, hash = new WeakMap(a)) {
if (typeofdata ! = ="object" || data == null) {
return data;
}
// Check whether the passed object to be copied already exists in the hash to avoid loop references
if (hash.has(data)) {
return hash.get(data);
}
const newData = Array.isArray(data) ? [] : {};
const dataKeys = Object.keys(data);
dataKeys.forEach((key) = > {
const current = data[key];
const typeString = Object.prototype.toString.call(current).toLowerCase();
if (typeofcurrent ! = ="object" || current == null) {
// Basic type
newData[key] = current;
return;
}
switch (typeString) {
case "[object array]":
newData[key] = [...deepCopy(current, hash)];
break;
case "[object set]":
newData[key] = new Set([...current.values()]);
break;
case "[object map]":
newData[key] = new Map([...current]);
break;
default:
// Common objects perform recursive operationshash.set(data, data); newData[key] = deepCopy(current, hash); }});return newData;
}
Copy the code
Array to heavy
ES6 Set
const uniqueArr = [...new Set(arr)];
const uniqueArr = Array.from(new Set(arr));
Copy the code
reduce
function unique(arr) {
// Sort first, if repeated, the content of the previous subscript is the same
return arr.sort().reduce((acc, current) = > {
if (acc.length == 0 || acc[acc.length - 1] !== current) {
acc.push(current);
}
returnacc; } []); }Copy the code
filter
function unique(arr) {
return arr.filter((element, index, array) = > {
return array.indexOf(element) == index;
});
}
Copy the code
Flattening an array
Flattening is done using the Reduce method
function flattenDeep(arr) {
return Array.isArray(arr)
? arr.reduce((acc, current) = > {
return [...acc, ...flattenDeep(current)];
}, [])
: [arr];
}
Copy the code
Simulation of the stack
function flattenDeep(arr) {
const stack = [...arr]; // Copy it flat to stack
const result = [];
while (stack.length) {
// Fetch the trailing value
const current = stack.pop();
if (Array.isArray(current)) {
// If the value is an array, push the stack again after flatteningstack.push(... current); }else {
// If the end is a normal value, store resultresult.unshift(current); }}return result;
}
Copy the code
Currie,
function curry(fn) {
return function curried(. args) {
if (args.length >= fn.length) {
// The passed parameter overrides all the visible parameters
fn.apply(this, args);
} else {
return function (. args2) {
return curried.apply(this, args.concat(args2)); }; }}; }Copy the code
Image stabilization
function debounce(fn, wait) {
let timer = null;
return () = > {
clearTimeout(timer);
timer = setTimeout(() = > {
fn.apply(this.Array.from(arguments));
}, wait);
};
}
Copy the code
The throttle
function throttle(fn, wait) {
let timer = null;
return () = > {
if(timer ! = =null) {
return;
}
timer = setTimeout(() = > {
fn.apply(this.Array.from(arguments));
timer = null;
}, wait);
};
}
Copy the code