Skip to content

关键字

new

js
function newFn(constructor, ...args) {
  // 创建空的实例对象
  const instance = {};
  // 如果原型链为对象,则实例对象 __proto__ 指向原型链
  if (isObject(constructor.prototype)) {
    instance.__proto__ = constructor.prototype;
  }
  // 构造器内部的 this 指向实例对象
  const result = constructor.apply(instance, args);
  // 如果返回值为非原始值,则覆盖实例对象
  return isObject(result) ? result : instance;
}
newFn(Foo); // new Foo();

instanceof

js
function instanceofFn(target, constructor) {
  // target 应为对象,constructor 应为函数
  if (!(isObject(target) && typeof constructor === 'function')) {
    return false;
  }
  // constructor.prototype 应为对象
  if (!isObject(constructor.prototype)) {
    throw new TypeError(
      "Function has non-object prototype 'null' in instanceof check",
    );
  }
  // 检查 constructor.prototype 是否在 target 的原型链中
  while (target) {
    if (target.__proto__ === constructor.prototype) {
      return true;
    }
    target = target.__proto__;
  }
  return false;
}
instanceofFn(foo, Array); // foo instanceof Array
Function.prototype[Symbol.hasInstance].call(Array, foo); // foo instanceof Array

async & await

js
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
  try {
    var info = gen[key](arg);
    var value = info.value;
  } catch (error) {
    reject(error);
    return;
  }
  if (info.done) {
    resolve(value);
  } else {
    Promise.resolve(value).then(_next, _throw);
  }
}
function _asyncToGenerator(fn) {
  return function () {
    var self = this,
      args = arguments;
    return new Promise(function (resolve, reject) {
      var gen = fn.apply(self, args);
      function _next(value) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value);
      }
      function _throw(err) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err);
      }
      _next(undefined);
    });
  };
}

内置对象

Array

js
class Array {
  reduce(callback, initValue) {
    let acc;
    if (initValue === void 0) {
      if (this.length === 0) {
        throw new TypeError('Reduce of empty array with no initial value');
      }
      acc = this[0];
      for (let i = 1; i < this.length; i++) {
        acc = callback(acc, this[i], i, this);
      }
    } else {
      acc = initValue;
      for (let i = 0; i < this.length; i++) {
        acc = callback(acc, this[i], i, this);
      }
    }
    return acc;
  }
  flat(depth = 1) {
    if (typeof depth !== 'number' || depth === 0) {
      return this;
    }
    let arr = [];
    for (let e of this) {
      arr = arr.concat(Array.isArray(e) ? e.flat(depth - 1) : [e]);
    }
    return arr;
  }
}

Promise

js
const STATUS = {
  PENDING: 'pending',
  FULFILLED: 'fulfilled',
  REJECTED: 'rejected',
};
class Promise {
  _status = 'pending';
  _value = void 0;
  _resolveQueue = [];
  _rejectQueue = [];

  constructor(executor) {
    const handle = (newStatus, queue) => (value) => {
      queueMicrotask(() => {
        if (this._status !== STATUS.PENDING) return;
        this._value = value;
        this._status = newStatus;
        while (queue.length) {
          queue.shift()(value);
        }
      });
    };
    const resolve = handle(STATUS.FULFILLED, this._resolveQueue);
    const reject = handle(STATUS.REJECTED, this._rejectQueue);
    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }
  then(onFulfilled, onRejected) {
    onFulfilled =
      typeof onFulfilled === 'function'
        ? onFulfilled
        : (v) => {
            return v;
          };
    onRejected =
      typeof onRejected === 'function'
        ? onRejected
        : (e) => {
            throw e;
          };
    return new Promise((resolve, reject) => {
      const handle = (callback) => (value) => {
        try {
          const result = callback(value);
          result instanceof Promise
            ? result.then(resolve, reject)
            : resolve(result);
        } catch (error) {
          reject(error);
        }
      };
      const resolveFn = handle(onFulfilled);
      const rejectFn = handle(onRejected);
      switch (this._status) {
        case STATUS.PENDING:
          this._resolveQueue.push(resolveFn);
          this._rejectQueue.push(rejectFn);
          break;
        case STATUS.FULFILLED:
          resolveFn(this._value);
          break;
        case STATUS.REJECTED:
          rejectFn(this._value);
          break;
        default:
          throw 'Promise 状态错误';
      }
    });
  }

  static resolve(value) {
    return value instanceof Promise
      ? value
      : new Promise((resolve) => resolve(value));
  }
  static reject(error) {
    return new Promise((resolve, reject) => reject(error));
  }
  static all(iterable) {
    let count = 0;
    const result = [];
    const array = [...iterable];
    return new Promise((resolve, reject) => {
      if (array.length === 0) {
        return resolve(result);
      }
      array.forEach((p, i) => {
        Promise.resolve(p).then((value) => {
          result[i] = value;
          if (++count === array.length) {
            resolve(result);
          }
        }, reject);
      });
    });
  }
  static race(iterable) {
    const array = [...iterable];
    return new Promise((resolve, reject) => {
      array.forEach((p) => {
        Promise.resolve(p).then(resolve, reject);
      });
    });
  }
}

A+ 规范

只要有属性 then 且值为函数的任何对象,都是 Promise

Function

js
class Function {
  call(context, ...args) {
    const key = Symbol();
    context[key] = this;
    const result = context[key](...args);
    delete context[key];
    return result;
  }
  bind(context, ...args) {
    const self = this;
    return function (...restArgs) {
      return self.apply(context, args.concat(restArgs));
    };
  }
}

Generator

js
/**生成器函数 */
function* fn() {
  yield 1;
  yield 2;
  yield 3;
  return 23;
}
/**生成器对象,继承于迭代器 */
const foo = fn();
foo.next(); // {value: 1, done: false}
  • 第一次执行 next 时,fn 只会执行到 yield 1; 而不会向下执行
  • 每次执行 next 时,fn 都将继续执行到下一个 yield
  • fn 执行完毕时,next 返回 {value: 23, done: true}
  • 此时再次调用 next 只会返回 {value: undefined, done: true}
js
function* fn() {
  console.log(yield 1);
  yield 2;
  yield 3;
}
const foo = fn();
foo.next(); // {value: 1, done: false}
foo.next(23);
// 23
// {value: 2, done: false}
  • 如果给 next 传入参数,这个参数将作为上一次 yield 的返回值