1 Handwritten Promise series
In the Promise of study, also written before relevant share articles, please see the "front-end [white] started from the perspective of Promise, Async/await and Shredded Code" .
1.1 Promise.all
//Handwritten promise.all
Promise .prototype._all = promiseList => {
//When the input is a promise list
const len = promiseList.length;
const result = [];
let count = 0 ;
//
return new Promise ( ( resolve,reject )=> {
//Loop through the promise events in the promise list
for ( let i = 0 ; i <len; i++){
//Traverse to the i-th promise event and determine whether the event succeeded or failed
promiseList[ i].then( data => {
result[i] = data;
count++;
//When traversing to the last promise, the length of the result array is the same as the length of the promise list, indicating success
count === len && resolve(result);
}, error => {
return reject(error);
})
}
})
}
Copy code
1.2 Promise.race
//Handwritten promise.race
Promise .prototype._race = promiseList => {
const len = promiseList.length;
return new Promise ( ( resolve,reject )=> {
//Loop through the promise events in the promise list
for ( let i = 0 ; i <len; i++){
promiseList[i]().then( data => {
return resolve(data);
}, error => {
return reject(error);
})
}
})
}
Copy code
1.3 Promise.finally
Promise .prototype._finally = function ( promiseFunc ) {
return this .then( data => Promise .resolve(promiseFunc()).then( data => data)
, error => Promise .reject(promiseFunc()).then( error => { throw error}))
}
Copy code
2 Handwriting Aysnc/Await
function asyncGenertor ( genFunc ) {
return new Promise ( ( resolve,reject )=> {
//Generate an iterator
const gen = genFunc();
const step = ( type,args )=> {
let next;
try {
next = gen[type](args);
} catch (e){
return reject(e);
}
//Get the values of done and value from next
const (done,value) = next;
//If the state of the iterator is true
if (done) return resolve(value);
Promise .resolve(value).then(
val = > step( "next" ,val),
err => step( "throw" ,err)
)
}
step( "next" );
})
}
Copy code
3 Deep copy
Deep copy: Copy all attribute values and the memory space of the value pointed to by the attribute address.
3.1 Deep copy of missing reference
When an object is encountered, a new object is opened, and then the attribute values of the second-level source object are completely copied to this newly opened object.
//Deep copy with missing reference
function deepClone ( obj ) {
//Determine whether the type of obj is object type
if (!obj && typeof obj !== "object" ) return ;
//Determine whether the object is an array type or an object type
let newObj = Array .isArray(obj)? []: {};
//Traverse the key-value pairs of obj
for ( const [key,value] of Object .entries(obj)){
newObj[key] = typeof value === "string" ? deepClone(value): value;
};
return newObj;
}
Copy code
3.2 Deep copy of the ultimate solution (stack and depth-first thinking)
The idea is: to introduce an array
function deepCopy ( obj ) {
//used to remove
duplicates const uniqueList = [];
//set the root node
let root = {};
//traverse the array
const loopList = [{
parent : root,
key : undefined ,
data : obj
}];
//Traverse the loop
while (loopList.length){
//Depth first-take out the last element of the array
const {parent,key,data} = loopList.pop();
//Initialize the assignment target, copy to when key--undefined Parent element, otherwise copy to child element
let result = parent;
if ( typeof key !== "undefined" ) result = parent[key] = {};
//When the data already exists
let uniqueData = uniqueList.find( item => item.source === data);
if (uniqueData){
parent[key] = uniqueData.target;
//Interrupt this cycle
continue ;
}
//When the data does not exist
//Save the source data, and copy the corresponding reference in the data
uniqueList.push({
source :data,
target :result
});
//Traverse the data
for ( let k in data){
if (data.hasOwnProperty(k)){
typeof data[k] === "object"
?
//next loop
loopList.push({
parent :result,
key :k,
data :data[k]
})
:
result[k] = data[k];
}
}
}
return root;
}
Copy code
4 Handwriting a singleton pattern
Singleton mode: Ensure that a class has only one instance, and provide a global access point to access it. The implementation method is generally to first determine whether the instance exists, if it exists, return directly, if it does not exist, create it and return.
//Create a singleton object, use closure
const getSingle = function ( func ) {
let result;
return function () {
return result || (result = func.apply( this , arguments ));
}
}
//Use Proxy to intercept
const proxy = function ( func ) {
let reuslt;
const handler = {
construct : function () {
if (!result) result = Reflect .construct(func, arguments );
return result;
}
}
return new Proxy (func,hendler);
}
Copy code
5 encapsulate an ajax function by hand
/*
Encapsulate your own ajax function
Parameter 1: {string} method request method
Parameter 2: {string} url request address
Parameter 2: {Object} params request parameters
Parameter 3: {function} done Callback function to be executed after the request is completed
*/
function ajax ( method,url,params,done ) {
//1. Create xhr object, compatible with writing
let xhr = window .XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject( "Microsoft.XMLHTTP" );
//Convert method to uppercase
method = method.toUpperCase();
//Parameter splicing
let newParams = [];
for ( let key in params){
newParams.push( ` ${key} = ${params[k]} ` );
}
let str = newParams.join( "&" );
//Determine the request method
if (method === "GET" ) url += `? ${str} ` ;
//Open the request method
xhr.open(method,url);
let data = null ;
if (method === "POST" ){
//Set the request header
xhr.setRequestHeader(( "Content-Type" , "application/x-www-form-urlencoded" ));
data = str;
}
xhr.send(data);
//Specify the xhr state change event processing function
//Execute the callback function
xhr.onreadystatechange = function () {
if ( this .readyState === 4 ) done( JSON .parse(xhr.responseText));
}
}
Copy code
6 Handwriting "Anti-shake" and "Throttling"
In the study of "Anti-shake" and "Throttling", I have also written related sharing articles before. Please refer to "One Net-The "Anti-shake" and "Throttling" Methods of Front End . "
6.1 Anti-shake
/*
func: The function to be processed for anti-shake processing
delay: the time to be delayed
immediate: whether to use immediate execution true immediate execution false non-immediate execution
*/
function debounce ( func,delay,immediate ) {
let timeout; //Timer
return function ( arguments ) {
//Determine whether the timer exists, clear it if it exists, and restart the timer count
if (timeout) clearTimeout (timeout );
Stabilizer the stabilizer//judgment is executed immediately or not immediately executed
IF (immediate) { //perform immediately
const in Flag = timeout;! //here negate operation
timeout = the setTimeout ( () => {
timeout = null ;
},delay);
//The function will be executed immediately after the event is triggered, and then the effect of the function can be continued without triggering the event within n seconds.
if (flag) func.call( this , arguments );
} else { //Non-immediate execution
timeout = setTimeout ( ()=> {
func.call( this , arguments );
},delay)
}
}
}
Copy code
6.2 Throttling
//Throttle-timer version
function throttle ( func, delay ) {
let timeout; //Define a timer mark
return function ( arguments ) {
//Determine whether there is a timer
if (!timeout){
//Create one Timer
timeout = setTimeout ( ()=> {
//The delay interval clears the timer
clearTimeout (timeout);
func.call( this , arguments );
},delay)
}
}
}
Copy code
7 Handwriting apply, bind, call
7.1 apply
- The parameters passed to the function are handled differently, and the other parts are the same as call.
- apply accepts the second parameter as an array-like object, here we use the method of judging whether it is an array-like object in the "JavaScript Definitive Guide".
Function .prototype._apply = function ( context ) {
if (context === null || context === undefined) {
context = window //The this value specified as null and undefined will automatically point to the global object (window in the browser)
} else {
context = Object (context) //this value of the original value (number, string, boolean) will point to the instance object of the original value
}
//JavaScript
function isArrayLike(o) {
if (o && //o null undefined
typeof o === 'object' && //o
isFinite(o.length) && //o.length
o.length >= 0 && //o.length
o.length === Math.floor(o.length) && //o.length
o.length < 4294967296) //o.length < 2^32
return true
else
return false
}
const specialPrototype = Symbol(' Symbol') //
context[specialPrototype] = this; // this context
let args = arguments[1]; //
let result
//
if (args) {
//
if (!Array.isArray(args) && !isArrayLike(args)) {
throw new TypeError('myApply ');
} else {
args = Array.from(args) //
result = context[specialPrototype](...args); //
}
} else {
result = context[specialPrototype](); //
}
delete context[specialPrototype]; //
return result; //
};
7.2 bind
-
:
- Object.create prototype fToBind
-
-
- new instanceof new context
- this+
Function.prototype._bind = function (objThis, ...params) {
const thisFn = this; // params( )
// secondParams
let fToBind = function (...secondParams) {
const isNew = this instanceof fToBind //this fToBind fToBind new
const context = isNew ? this : Object(objThis) //new this , objThis
return thisFn.call(context, ...params, ...secondParams); // call this ,
};
if (thisFn.prototype) {
// prototype fToBind prototype
fToBind.prototype = Object.create(thisFn.prototype);
}
return fToBind; //
};
7.3 call
- call , this
- context , this context
Function.prototype._call = function (context, ...arr) {
if (context === null || context === undefined) {
// null undefined this ( window)
context = window
} else {
context = Object(context) // this
}
const specialPrototype = Symbol(' Symbol') //
context[specialPrototype] = this; // this context
let result = context[specialPrototype](...arr); //
delete context[specialPrototype]; //
return result; //
};
8
8.1
function fatherUser(username, password) {
let _password = password
this.username = username
fatherUser.prototype.login = function () {
console.log(this.username + ' ' + _password)
}
}
function sonUser(username, password) {
fatherUser.call(this, username, password)
this.articles = 3 //
}
const yichuanUser = new sonUser('yichuan', 'xxx')
console.log(yichuanUser.username) //yichuan
console.log(yichuanUser.username) //xxx
console.log(yichuanUser.login()) //TypeError: yichuanUser.login is not a function
8.2
function fatherUser(username, password) {
let _password = password
this.username = username
fatherUser.prototype.login = function () {
console.log(this.username + ' fatherUser ' + _password)
}
}
function sonUser(username, password) {
fatherUser.call(this, username, password) // fatherUser
this.articles = 3 //
}
= sonUser.prototype new new fatherUser (); //perform fatherUser second constructor
const yichuanUser = new new sonUser ( 'Yichuan' , 'XXX' )
copying the code
8.3 Parasitic combinatorial inheritance
The above inheritance method is flawed, so just write this method.
function Parent() {
this .name = 'parent' ;
}
function Child () {
Parent.call( this );
this .type = 'children' ;
}
Child.prototype = Object .create(Parent.prototype);
Child.prototype.constructor = Child;
Copy code
Reference article
"Summary of JavaScript Skills for Advanced Frontends"
Write at the end
I am a front-end Xiaocai. Thank you for reading. I will continue to share more excellent articles with you. This article refers to a large number of books and articles. If there are errors or omissions, I hope I can correct them.