Function.prototype.myCall = function () {
let thisVal = arguments[0] // 存call第一个参数执行上下文
const isStrict = (function () { return this === undefined })() // 判断当前环境是否是严格模式
if (!isStrict) { // 非严格模式
if (thisVal === null || thisVal === undefined) { // thisVal 没传或者是null, undefined
thisVal = (function () { return this })() // 则赋值为window或者node环境参数
}
} else { // 严格模式
const thisValType = typeof thisVal // 先处理可能输入的不同数据格式
if (thisValType === 'number') {
thisVal = new Number(thisVal)
}
if (thisValType === 'string') {
thisVal = new String(thisVal)
}
if (thisValType === 'boolean') {
thisVal = new Boolean(thisVal)
}
}
const otherParams = [...arguments].slice(1) // call其他参数
const fn = this // 当前this就是调用call的方法
if (thisVal === null || thisVal === undefined) { // 严格模式 并且没有指定第一个参数或者第一个参数的值本身就是null或undefined,此时将目标函数当成普通函数执行并返回其结果即可
return fn(...otherParams)
}
// 否则,让目标函数成为thisArg对象的成员方法,然后调用它 ???
// 直观上来看,可以直接把目标函数赋值给对象属性,比如func属性,但是可能func属性本身就存在于thisArg对象上
// 所以,为了防止覆盖掉thisArg对象的原有属性,必须创建一个唯一的属性名,可以用Symbol实现,如果环境不支持Symbol,可以通过uuid算法来构造一个唯一值。
var uniquePropName = Symbol(thisVal)
thisVal[uniquePropName] = fn
return thisVal[uniquePropName](...otherParams)
}
Function.prototype.myApply = function () {
let thisVal = arguments[0] // 存call第一个参数执行上下文
const isStrict = (function () { return this === undefined })() // 判断当前环境是否是严格模式
if (!isStrict) { // 非严格模式
if (thisVal === null || thisVal === undefined) { // thisVal 没传或者是null, undefined
thisVal = (function () { return this })() // 则赋值为window或者node环境参数
}
} else { // 严格模式
const thisValType = typeof thisVal // 先处理可能输入的不同数据格式
if (thisValType === 'number') {
thisVal = new Number(thisVal)
}
if (thisValType === 'string') {
thisVal = new String(thisVal)
}
if (thisValType === 'boolean') {
thisVal = new Boolean(thisVal)
}
}
const otherParams = Array.isArray(arguments[1]) ? [...arguments[1]] : arguments[1] // call其他参数
const fn = this // 当前this就是调用call的方法
if (thisVal === null || thisVal === undefined) { // 严格模式 并且没有指定第一个参数或者第一个参数的值本身就是null或undefined,此时将目标函数当成普通函数执行并返回其结果即可
return fn(...otherParams)
}
// 否则,让目标函数成为thisArg对象的成员方法,然后调用它 ???
// 直观上来看,可以直接把目标函数赋值给对象属性,比如func属性,但是可能func属性本身就存在于thisArg对象上
// 所以,为了防止覆盖掉thisArg对象的原有属性,必须创建一个唯一的属性名,可以用Symbol实现,如果环境不支持Symbol,可以通过uuid算法来构造一个唯一值。
var uniquePropName = Symbol(thisVal)
thisVal[uniquePropName] = fn
return thisVal[uniquePropName](...otherParams)
}
function curry(fn) {
let args = []
function curried() {
args = [...args, ...arguments]
return curried
}
curried.toString = function(){
return fn.myCall(null, ...args)
}
return curried
}
Promise.all = function (iterators) {
return new Promise((resolve, reject) => {
if (!iterators || iterators.length === 0) {
resolve([]);
} else {
let count = 0; // 计数器,用于判断所有任务是否执行完成
let result = []; // 结果数组
for (let i = 0; i < iterators.length; i++) {
// 考虑到iterators[i]可能是普通对象,则统一包装为Promise对象
Promise.resolve(iterators[i]).then(
(data) => {
result[i] = data; // 按顺序保存对应的结果
// 当所有任务都执行完成后,再统一返回结果
if (++count === iterators.length) {
resolve(result);
}
},
(err) => {
reject(err); // 任何一个Promise对象执行失败,则调用reject()方法
return;
}
);
}
}
});
};
Promise.race = function (iterators) {
return new Promise((resolve, reject) => {
for (const iter of iterators) {
Promise.resolve(iter)
.then((res) => {
resolve(res);
})
.catch((e) => {
reject(e);
});
}
});
};