手写实现
Call, Apply, Bind
js
const obj = { x : '100px' };
Function.prototype.myCall = function(thisArg, ...args) {
if (typeof this !== 'function') {
throw new Error('需要被函数来Call');
}
// 如果thisArg为空,则挂载到全局上
thisArg = (thisArg == null) ? globalThis : Object(thisArg);
// 挂载函数到目标对象上
const fnSym = Symbol('fn');
thisArg[fnSym] = this;
const result = thisArg[fnSym](...args);
// 记得清理挂载
delete thisArg[fnSym];
return result;
}
function myFunc(x,y,z) {
console.log(`x=${x},y=${y},z=${z}`);
console.log(`this.x=${this.x}`);
setTimeout(() => {
console.log('延迟检查 this', {...this});
}, 0);
}
console.log(myFunc.myCall(obj,1,2,3));
Function.prototype.myApply = function(thisArg, arrayParam) {
if (typeof this !== 'function') {
throw new Error('需要函数调用');
}
thisArg = (thisArg == null) ? globalThis : Object(thisArg);
const fnSym = Symbol('fn');
thisArg[fnSym] = this;
let n = arrayParam?.length;
let result = null;
if (n===0) {
result = thisArg[fnSym]();
}
let args = [];
for(let i = 0; i<n ; i++) {
args.push(arrayParam[i]);
}
result = thisArg[fnSym](...args);
delete thisArg[fnSym];
return result;
}
console.log(myFunc.myApply(obj,[1,2,3]));
Function.prototype.myBind = function(thisArg, ...args) {
if (typeof this !== 'function') {
throw new Error('需要函数调用');
}
// 获取需要绑定的函数
const targetFn = this;
const boundFn = function(...boundArgs) {
const newThis = (this instanceof boundFn) ? this : thisArg;
return targetFn.myApply(newThis, args.concat(boundArgs));
}
// 保持函数原型链
if (targetFn.prototype) {
boundFn.prototype = Object.create(targetFn.prototype);
}
return boundFn;
}
function fn(a, b, c, ...args) {
console.log(`a=${a}, b=${b}, c=${c}`)
setTimeout(() => {
console.log('延迟检查 this', {...this});
}, 0);
return args
}
const newFn = fn.myBind(obj, 1, 2)
console.log(newFn(3,4,5))Promise
js
class MyPromise {
state = 'pending' // 状态
value = undefined // 成功后的数值
reason = undefined // 失败的结果
resolveCallbacks = [] // 保存成功的回调函数
rejectCallbacks = [] // 保存失败的回调函数
constructor(func) {
// 外面定义MyPromise时,定义的函数内部最终运行resolve()的对应函数
const resolveHandler = (value) => {
if (this.state !== 'pending')
return
const resolveValue = (val)=>{
queueMicrotask(()=>{
if(val instanceof MyPromise) {
val.then(v=>resolveValue(v),
(err)=>rejectHandler(err))
}else if(val && typeof val.then === 'function'){
val.then(resolveValue, rejectHandler)
}else {
this.state = 'fulfilled'
this.value = val
this.resolveCallbacks.forEach((fn)=>{queueMicrotask(fn)})
}
})
}
resolveValue(value)
// queueMicrotask(() => {
// if (this.state === 'pending') {
// this.state = 'fulfilled'
// this.value = value
// this.resolveCallbacks.forEach(fn => queueMicrotask(fn))
// }
// })
// if (this.state === 'pending') {
// this.state = 'fulfilled'
// this.value = value
// this.resolveCallbacks.forEach(fn => queueMicrotask(fn))
// }
}
const rejectHandler = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
this.value = reason
this.rejectCallbacks.forEach(fn => queueMicrotask(fn))
}
}
try {
// 定义MyPromise时,传参的函数会立刻执行
func(resolveHandler, rejectHandler)
} catch (err) {
rejectHandler(err)
}
}
then(fn1, fn2) {
fn1 = typeof fn1 === 'function' ? fn1 : (v) => v
// 当没有fn2时,说明不是catch过来的,但如果后续走进了onReject流程,则需要让fn2继续抛出错误
fn2 = typeof fn2 === 'function' ? fn2 : (e) => { throw e; }
if (this.state === 'pending') {
return new MyPromise((resolve, reject) => {
// 存储起来,用于状态改变后then的调用
this.resolveCallbacks.push(() => {
try {
const newValue = fn1(this.value)
resolve(newValue)
} catch (err) {
reject(err)
}
})
this.rejectCallbacks.push(() => {
try {
const newReason = fn2(this.reason)
// 只要fn2正常通过,则继续resolve流程
resolve(newReason)
} catch (err) {
reject(err)
}
})
})
}
if (this.state === 'fulfilled') {
return new MyPromise((resolve, reject) => {
try {
const newValue = fn1(this.value)
resolve(newValue)
} catch (err) {
reject(err)
}
})
}
if (this.state === 'rejected') {
return new MyPromise((resolve, reject) => {
try {
const newReason = fn2(this.reason)
// 只要fn2正常通过,则继续resolve流程
resolve(newReason)
} catch (err) {
reject(err)
}
})
}
}
catch(fn) {
return this.then((v) => v, fn)
}
}
MyPromise.resolve = function (value) {
return new MyPromise((resolve, reject) => resolve(value))
}
MyPromise.reject = function (reason) {
return new MyPromise((resolve, reject) => reject(reason))
}
MyPromise.all = function (promiseList = []) {
return new MyPromise((resolve, reject) => {
const resultList = new Array(promiseList.length);
if (promiseList.length === 0)
resolve([])
let count = 0;
promiseList.forEach((p, index) => {
p.then(data => {
resultList[index] = data; // 按索引存储
if (++count === promiseList.length)
resolve(resultList);
}).catch(reject);
});
});
}
MyPromise.race = function (promiseList = []) {
return new MyPromise((resolve, reject) => {
let flag = true
promiseList.forEach(p => {
p.then(data => {
if (flag) {
resolve(data)
flag = false
}
}).catch(err => {
reject(err)
})
})
})
}