ts 实现常见前端手写题

93 阅读1分钟

Object.create

由于ts可以进行类型检查,所以不用写proto的判断条件了 PropertyDescriptorMap 是ts内置的类型,用于描述属性描述符的映射类型

function createObject(proto: object, propertiesObject?: PropertyDescriptorMap) {
  // 创建新对象
  function F() { }
  F.prototype = proto
  const obj = new F()

  if (propertiesObject !== undefined) {
    Object.defineProperties(obj, propertiesObject)
  }

  return obj
}
}

instanceof

function myInstanceof(instance: any, constructor: Function): boolean {
  // 处理原始类型和 null
  if (instance === null || typeof instance !== 'object') {
    return false
  }

  // 获取实例的原型
  let proto = Object.getPrototypeOf(instance)
  // 获取构造函数的 prototype
  const prototype = constructor.prototype

  // 沿着原型链查找
  while (proto !== null) {
    if (proto === prototype) {
      return true
    }
    proto = Object.getPrototypeOf(proto)
  }

  return false
}

call, apply

interface Function {
  myCall(thisArg: any, ...args: any[]): any
}

Function.prototype.myCall = function (thisArg: any, ...args: any[]): any {
  // 处理 thisArg 为 null 或 undefined 的情况
  thisArg = thisArg ?? window

  // 防止属性名冲突,使用 Symbol
  const fn = Symbol('fn')

  // 将函数作为传入对象的方法
  thisArg[fn] = this

  // 执行函数并获取结果
  const result = thisArg[fn](...args)

  // 删除临时属性
  delete thisArg[fn]

  return result
}
interface Function {
  myApply(thisArg: any, args?: any[]): any
}

Function.prototype.myApply = function (thisArg: any, args?: any[]): any {
  // 处理 thisArg 为 null 或 undefined 的情况
  thisArg = thisArg ?? window

  // 防止属性名冲突,使用 Symbol
  const fn = Symbol('fn')

  // 将函数作为传入对象的方法
  thisArg[fn] = this

  // 执行函数并获取结果
  const result = thisArg[fn](...(args || []))

  // 删除临时属性
  delete thisArg[fn]

  return result
}

new

function myNew<T extends Function>(constructor: T, ...args: any[]): any {
  // 1. 创建一个新对象,并将其原型指向构造函数的 prototype
  const obj = Object.create(constructor.prototype)

  // 2. 执行构造函数,并将 this 指向新创建的对象
  const result = constructor.apply(obj, args)

  // 3. 判断构造函数是否返回了一个对象
  // 如果返回值是对象,则返回该对象
  // 如果返回值不是对象,则返回新创建的实例对象
  return result instanceof Object ? result : obj
}