JavaScript基础知识(二)——手写"源码"
Promise Promise 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 class MyPromise { static PENDING = "pending" static FULFILLED = "fulfilled" static REJECTED = "rejected" constructor (func ) { this .PromiseState = MyPromise .PENDING this .PromiseResult = null this .onFulfilledCallBacks = [] this .onRejectedCallBacks = [] func (this .resolve .bind (this ), this .resolve .bind (this )) } resolve (result ) { if (this .PromiseState === MyPromise .PENDING ) { this .PromiseState = MyPromise .FULFILLED this .PromiseResult = result while (this .onFulfilledCallBacks .length ) { this .onFulfilledCallBacks .shift ()(result) } } } reject (reason ) { if (this .PromiseState === this .PENDING ) { this .PromiseState = this .REJECTED this .PromiseResult = reason while (this .onRejectedCallBacks .length ) { this .onRejectedCallBacks .shift ()(reason) } } } then (onFulfilled, onRejected ) { onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (val ) => val onRejected = typeof onRejected === "function" ? onRejected : (reason ) => { throw reason } const thenpromise = new MyPromise ((resolve, reject ) => { const resolvep = (cb ) => { setTimeout (() => { try { const x = cb (this .PromiseResult ) if (x === thenpromise) { throw new Error ("err" ) } if (x instanceof MyPromise ) { x.then (resolve, reject) } else { resolve (x) } } catch (err) { reject (err) } }) } if (this .PromiseState === MyPromise .FULFILLED ) { resolvep (onFulfilled) } else if (this .PromiseState === MyPromise .REJECTED ) { resolvep (onRejected) } else { this .onFulfilledCallBacks .push (resolvep.bind (this , onFulfilled)) this .onRejectedCallBacks .push (resolvep.bind (this , onRejected)) } }) return thenpromise } } const mp = new MyPromise ((res, rej ) => { setTimeout (() => { console .log (1 ) res (2222 ) console .log (3 ) }) }).then ((s ) => { console .log (s) })
Promise.all 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Promise .myAll = (promises ) => { return new Promise ((resolve, reject ) => { let count = 0 let result = [] const len = promises.length || 0 if (len === 0 ) { return resolve ([]) } promises.forEach ((p, i ) => { Promise .resolve (p) .then ((res ) => { count += 1 result[i] = res if (count === len) { resolve (result) } }) .catch (reject) }) }) }
Promise.allSettled 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 Promise .myAllSettled = (promises ) => { return new Promise ((resolve, reject ) => { let counter = 0 const result = [] const len = promises.length || 0 if (len === 0 ) { return resolve ([]) } promises.forEach ((p, i ) => { Promise .resolve (p).then ( (res ) => { counter += 1 result[i] = { status : "fulfilled" , value : res } if (counter === len) { resolve (result) } }, (rej ) => { counter += 1 result[i] = { status : "rejected" , value : rej } if (counter === len) { reject (result) } } ) }) }) }
Promise.race 1 2 3 4 5 6 7 8 9 10 11 12 13 Promise .myRace = (promises ) => { return new Promise (function (resolve, reject ) { promises.forEach ((p ) => { Promise .resolve (p).then (resolve, reject) }) }) }
Promise.any 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Promise .myAny = (promises ) => { let counter = 0 return new Promise ((resolve, reject ) => { promises.forEach ((p ) => { Promise .resolve (p).then (resolve, (err ) => { counter += 1 if (counter === promises.length ) { reject ("全都不成功!" ) } }) }) }) }
浅拷贝 1 2 3 4 5 6 7 8 9 10 11 12 const newobj1 = Object .assign ({}, obj)const newobj2 = { ...obj }const newArr1 = Array .from (arr)const newArr2 = [...arr]const newArr3 = arr.slice ()const newArr4 = arr.concat ([])const newArr5 = arr.filter ((val ) => val)const newArr6 = arr.map ((val ) => val)
深拷贝 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 //手写深拷贝 const obj1 = JSON.parse(JSON.stringify(obj)) const obj2 = structuredClone(obj) function deepClone(obj, wk = new WeakMap()) { if (obj === null || typeof obj !== "object") return obj if (obj instanceof Date) return new Date(obj) if (obj instanceof RegExp) return new RegExp(obj) if (obj instanceof HTMLElement) return obj if (wk.has(obj)) { return wk.get(obj) } let target = Array.isArray(obj) ? [] : {} wk.set(obj, target) Reflect.ownKeys(obj).forEach((item) => { if (typeof obj[item] === "object" && obj[item] !== null) { target[item] = deepClone(obj[item], wk) } else { target[item] = obj[item] } }) return target }
数组去重 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 function norepeatArr (arr ) { for (let i = 0 , len = arr.length ; i < len; i++) { for (let j = i + 1 ; j < len; j++) { if (arr[i] === arr[j] || Object .is (arr[i], arr[j])) { arr.slice (j, 1 ) } } } return arr } function norepeatArr (arr ) { let newArr = [] arr.forEach ((v, i ) => { if (newArr.indexOf (v) === i) { newArr.push (v) } }) return newArr } function norepeatArr2 (arr ) { let map = new Map () arr.forEach ((v, i ) => { if (!map.has (v)) { map.set (v, i) } }) return [...map.keys ()] } function norepeatArr (arr ) { return [...new Set (arr)] }
多维数组展平 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 const newArr = arr.flat (1 ) function flatArr1 (arr ) { if (!arr.length ) { return } return arr.reduce ((pre, cur ) => { return Array .isArray (cur) ? [...pre, ...flatArr (cur)] : [...pre, cur] }, []) } function flatArr2 (arr ) { if (!arr.length ) return while ( arr.some ((item ) => { return Array .isArray (item) }) ) { arr = [].concat (...arr) } } function flatArr3 (arr, depth = 1 , resArr = [] ) { for (const item of arr) { if (Array .isArray (item) && depth > 0 ) { flatArr2 (item, depth - 1 , resArr) } else { resArr.push (item) } } return resArr }
防抖和节流 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 function debounce (func, timer = 100 , immediate = false ) { let setTime = null return function (...args ) { setTime && clearTimeout (setTime) const that = this if (immediate) { let flag = !setTime if (flag) { func.apply (that, args) } setTime = setTimeout (() => { setTime = null }, timer) } else { setTime = setTimeout (() => { func.apply (that, args) }, timer) } } } function throttle (func, timer = 2000 ) { let t1 = 0 return function (...args ) { const that = this let t2 = new Date () if (t2 - t1 >= timer) { func.apply (that, args) t1 = new Date () } } }
setInterval 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function mySetInterval (func, delay = 1000 , maxcounter = 10 ) { let counter = 0 let timer = null let setfunction = function ( ) { func.call (null ) counter++ timer = setTimeout (() => { setfunction () }, delay) if (counter > maxcounter) { timer && clearTimeout (timer) return } } setTimeout (() => { setfunction () }, delay) }
Object.is 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 function myObjectIs (a, b ) { if (a === b) return a !== 0 || 1 / a === 1 / b return a !== a && b !== b } console .log (myObjectIs (1 , 1 )) console .log (myObjectIs (1 , 2 )) console .log (myObjectIs ([], [])) console .log (myObjectIs ([], {})) console .log (myObjectIs (0 , 0 )) console .log (myObjectIs (+0 , +0 )) console .log (myObjectIs (+0 , -0 )) console .log (myObjectIs (NaN , 0 )) console .log (myObjectIs (NaN , NaN ))
new 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function _new (fn ) { const args = Array .prototype .slice .call (arguments , 1 ) const newObj = {} newObj.__proto__ = fn.prototype fn.apply (newObj, args) return newObj } const obj1 = _new (obj,'name1' ,'age1' )
apply、call、bind 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 Function .prototype .myCall = function (targetFunc, ...args ) { targetFunc = targetFunc || window const symbolKey = Symbol () targetFunc[symbolKey] = this const res = targetFunc[symbolKey](...args) delete targetFunc[symbolKey] return res } Function .prototype .myApply = function (targetFunc, args ) { targetFunc = targetFunc || window const symbolKey = Symbol () targetFunc[symbolKey] = this const res = targetFunc[symbolKey](...args) delete targetFunc[symbolKey] return res } Function .prototype .myBind = function (targetFunc, ...args ) { targetFunc = targetFunc || window const symbolKey = Symbol () const that = this targetFunc[symbolKey] = this return function (...innerargs ) { if (this instanceof that) { this [symbolKey] = that this [symbolKey](...[...args, ...innerargs]) } const res = targetFunc[symbolKey](...[...args, ...innerargs]) return res } }
ajax 1 2 3 4 5 6 7 8 9 10 11 12 function ajax (url ) { const xhr = new XMLHttpRequest () xhr.open ("GET" , url, false ) xhr.setRequestHeader ("Content-Type" , "application/json" ) xhr.onreadystatechange = function ( ) { if (xhr.readyState != 4 ) return if (xhr.status === 200 || xhr.status == 304 ) { console .log (xhr.responseText ) } } xhr.send () }