【前端手写专题】bind、call、apply、Promise常见方法

181 阅读2分钟

这里总结一下一些前端常见手写。 我把我之前写的文章进行一个总结放在一起。以前是在其他博客网站上写的。

这里直接看代码

bind

Function.prototype.bind = function (...args) {
    if (typeof this !== 'function') {
        throw new TypeError(`${JSON.stringify(this)} is not a function`)
    } 
    const func = this;
    const [This, ...pervArgs] = args;
    return function (...rest) {
        if (new.target) {
            return new func(...pervArgs, ...rest);
        }
        return func.apply(This, pervArgs.concat(rest));
    }
}

call

Function.prototype.myCall = function (_this, ...args) {
  // call方法可以用来改变方法调用的this指向
  const func = this;
  if (typeof func !== "function") {
    // 类型判断
    throw TypeError("this is not a function");
  }
  if (typeof _this !== "object") {
    // 如果绑定的this不是一个对象
    _this = Object(_this);
  }
  const random = Math.random().toString(16).substring(2);
  Object.defineProperty(_this, "fn" + random, {
    value: func,
    enumerable: false,
  });
  const result = _this["fn" + random](...args);
  // 这里在_this上添加了一个属性,需要删除
  delete _this.fn;
  return result;
};

apply

Function.prototype.myApply = function (_this, args) {
  const func = this;
  if (typeof func !== "function") {
    // 类型判断
    throw TypeError("this is not a function");
  }
  if (!Array.isArray(args)) {
    throw TypeError("arg is not a array");
  }
  return func.myCall(_this, ...args);
};

Promise.allSettled

Promise.myAllSettled = function (proms) {
  return new Promise((resolve, reject) => {
    let resolvedCount = 0;
    let count = 0;
    const results = [];
    for (const prom of proms) {
      let i = count;
      count++;
      Promise.resolve(prom)
        .then(
          (data) => {
            resolvedCount++;
            results[i] = {
              status: "fullfilled",
              value: data,
            };
          },
          (reason) => {
            resolvedCount++;
            results[i] = {
              status: "rejected",
              reason,
            };
          }
        )
        .finally(() => {
          if (resolvedCount >= count) {
            resolve(results);
          }
        });
    }
  });
};

Promise.finally

Promise.prototype.finally = function (onSettled) {
    return this.then(data=>{ // then返回的也是一个Promise对象
        onSettled(); // 执行回调,但不传递数据
        return data; // 保证返回的Promise对象的数据一致
    },reason=>{
        onSettled();
        throw reason; // 保证返回的Promise对象的数据状态一致
    })
}

Promise.all

Promise.all = function (proms) {

    return new Promise((resolve, reject) => {
        try {
            let count = 0; // 有多少个proms
            let resolvedCount = 0; // 有多少个promise已经resolve

            let results = [] // resolve的结果是一个数组

            for (const pro of proms) { // proms不一定是数组,应该是迭代器
                let curIndex = count; // 记录这个promise resolve后在返回数组的下标
                count++;

                Promise.resolve(pro).then(data => { // 有可能不是一个promise,所以需要包装一下

                    results[curIndex] = data;
                    resolvedCount++;
                    if (count === resolvedCount) {
                        // 所有promise已经resolved,触发返回Promise的resolve
                        resolve(results);
                    }
                }, reject) // 有一个错误了就调用reject
            }
            if (count === 0) {
                // 有可能传进来的是一个空数组
                resolve(results);
            }
        } catch (error) {
            reject(error)  // 如果过程中出现错误,直接触发返回promise的reject
        }
    })
}