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
}