深度克隆、call、apply、bind、new、promsie

67 阅读2分钟
// 深度克隆
function deepClone (Origin, Target) {
  let strCall = Object.prototype.toString.call,
    strArr = '[object, Array]';
  if (!Target) {
    Target = strCall(Origin) === strArr ? [] : {};
  }
  // 遍历 key
  for (let prop in Origin) {
    if (Origin.hasOwnProperty(prop)) {
      // 判断是不是自己身上的属性,而不是原型链上的
      if (Origin[prop] !== null && strCall(Origin[prop]) === 'object') {
        // 判断是不是对象或者数组
        Target[prop] = strCall(Origin[prop]) === strArr ? [] : {};
        deepClone(Origin[prop], Target[prop]);
      } else {
        Target[prop] = Origin[prop];
      }
    }
  }
}
// call
Function.prototype.myCall = function (params, ...args) {
  if (typeof this !== 'function') {
    throw new Error("Type error");
  }
  params = params || window;
  params.fn = this;
  // const args = Array.prototype.slice.call(arguments, 1); // 获取参数
  let result = params.fn(...args);
  delete params.fn;
  return result;
};
// apply
Function.prototype.myApply = function (params, args) {
  if (typeof this !== 'function') {
    throw new Error("Type error");
  }
  params = params || window;
  params.fn = this;
  let result = params.fn(...args);
  delete params.fn;
  return result;
};
// bind
Function.prototype.myBind = function (params, ...args) {
  if (typeof this !== 'function') {
    throw new Error("Type error");
  }
  params = params || window;
  let fn = this;
  return function Fn () {
    // 用做构造函数时,this指向当前实例
    return fn.apply(this instanceof Fn ? this : params, args.concat(...arguments));
  };
};

// new
function myNew (content, ...args) {
  // 隐式的创建一个this对象
  const _this = new Object();
  // this.__proto__指向构造函数的原型
  _this.__proto__ = content.prototype;
  const res = content.apply(obj, args);
  // 并隐式的返回,如果构造函数的的结果是引用值,直接返回,如果不是返回创建的this
  return typeof res === 'object' ? res : obj;
}

// promise
class myPromise {
  static PENDING = 'pending';
  static FULFILLED = 'fulfilled';
  static REJECTED = 'rejected';
  constructor(fn) {
    this.result = null; // 设置初始值
    this.promiseState = myPromise.PENDING; // 设置初始状态
    this.onFulfilledCallback = []; // 成功的回调
    this.onRejectedCallback = []; // 失败的回调
    try {
      fn(this.resolve.bind(this), this.reject.bind(this));
    } catch (e) {
      this.reject(e);
    }
  }
  resolve (value) {
    if (this.promiseState === myPromise.PENDING) {
      this.result = value;
      this.promiseState = myPromise.FULFILLED;
      this.onFulfilledCallback.forEach(cb => cb());
    }
  }
  reject (reason) {
    if (this.promiseState === myPromise.PENDING) {
      this.result = reason;
      this.promiseState = myPromise.REJECTED;
      this.onRejectedCallback.forEach(cb => cb());
    }
  }
  then (onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => {
      throw reason;
    };
    let promise2 = new myPromise((resolve, reject) => {
      switch (this.promiseState) {
        case myPromise.FULFILLED:
          setTimeout(() => {
            try {
              let x = onFulfilled(this.result);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
              throw e;
            }
          });
          break;
        case myPromise.REJECTED:
          setTimeout(() => {
            try {
              let x = onRejected(this.result);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
              throw e;
            }
          });
          break;
        case myPromise.PENDING:
          this.onFulfilledCallback.push(() => {
            setTimeout(() => {
              try {
                let x = onFulfilled(this.result);
                resolvePromise(promise2, x, resolve, reject);
              } catch (e) {
                reject(e);
                throw e;
              }
            });
          });
          this.onRejectedCallback.push(() => {
            setTimeout(() => {
              try {
                let x = onRejected(this.result);
                resolvePromise(promise2, x, resolve, reject);
              } catch (e) {
                reject(e);
                throw e;
              }
            });
          });
          break;
      }
    });
    return promise2;
  }
}
function resolvePromise (promise2, x, resolve, reject) {
  // 如果 x 和 promise2 指向同一对象,会造成死循环,以 TypeError 拒绝 promise
  if (x === promise2) {
    return reject(new TypeError("Chaining cycle detected for promise"));
  }
  if (x instanceof myPromise) {
    // 如果 x 为 promise,则使用 promise2 接受 x 的状态继续执行
    x.then(y => {
      resolvePromise(promise2, y, resolve, reject);
    }, reject);
  } else if (x !== null && (typeof x === 'function' || typeof x === 'object')) {
    // 如果 x 为对象或者函数
    // 将 x.then 赋值给 then, 如果取值 x.then 抛出异常 e ,以 e 为据因拒绝 promise
    let then;
    try {
      then = x.then;
    } catch (e) {
      reject(e);
    }
    if (typeof then === 'function') {
      // 如果 then 是函数,将 x 作为函数的作用域 this 调用
      let called = false; // 避免多次调用
      try {
        then.call(x, y => {
          if (called) return;
          called = true;
          resolvePromise(promise2, y, resolve, reject);
        }, r => {
          if (called) return;
          called = true;
          reject(r);
        });
      } catch (e) {
        if (called) return;
        called = true;
        reject(e);
      }
    } else {
      // 如果 then 不是函数,以 x 为参数执行promise
      reject(x);
    }
  } else {
    // 如果 x 不为对象或者函数,以 x 为参数执行 promise
    return resolve(x);
  }
}