手写 typeof
ts
import { DataType } from '../types';
export function typeOf(obj: unknown): DataType {
// 判断 Null
if (obj === null) return 'null';
if (typeof obj === 'object') {
// 引用数据类型,使用 Object.prototype.toString.call 判断
return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
} else {
// 原始数据类型,使用 typeof 判断
return typeof obj;
}
}
mdx
// 使用示例
import { typeOf } from 'sth';
typeOf(2); // number
typeOf(true); // boolean
// 原生 typeof 无法正确判断引用数据类型的类型
typeof []; // object
typeof null; // object
typeof /a/; // object
// typeOf 可以正确判断引用数据类型的类型
typeOf([]); // array
typeOf(null); // null
typeOf(/a/); // regexp
手写 instanceof
ts
export function instanceOf(obj: unknown, constructor: any): boolean {
// 获取对象的 prototype 属性
let proto = Object.getPrototypeOf(obj);
// 获取构造函数的 prototype 属性
const prototype = constructor.prototype;
// 遍历对象的原型链
while (true) {
// 原型链遍历结束,未找到相同的 prototype 属性
if (proto === null) return false;
// 找到了相同的 prototype 属性
if (proto === prototype) return true;
// 未找到且未结束,继续遍历
proto = Object.getPrototypeOf(proto);
}
}
mdx
// 使用示例
import { instanceOf } from 'sth';
instanceOf([], Array); // true
instanceOf({}, Object); // true
// 原生 instanceof 无法正确判断原始数据类型的类型
2 instanceof Number; // false
// instanceOf 可以正确判断原始数据类型的类型
instanceOf(2, Number); // true
手写 new
ts
export function New(...argv: any): object | Function {
const constructor: unknown = Array.prototype.shift.call(arguments);
if (typeof constructor !== 'function') {
throw new Error(`Uncaught TypeError: constructor should be a function`);
}
// 创建一个原型为构造函数的新对象
const obj = Object.create(constructor.prototype);
// 执行构造函数,并将 this 指向对象
const res = constructor.apply(obj, arguments);
// 执行结果是引用类型,则返回执行结果;是值类型,则返回创建的对象
if (res !== null && (typeof res === 'object' || typeof res === 'function')) {
return res;
} else {
return obj;
}
}
mdx
import { New } from 'sth';
function Person(name: string, age: number) {
this.name = name;
this.age = age;
this.introduce = function (): string {
return 'My name is ' + this.name + ', ' + this.age + ' years old.';
};
}
const person: any = New(Person, 'Li Lei', 18);
person.name ; // 'Li Lei'
person.age; //18
person.introduce(); // 'My name is Li Lei, 18 years old.'
function PlainObject(a: any) {
this.b = 2;
return {
a,
};
}
const object: any = New(PlainObject, 1);
object.a; // 1
function IntNumber(a: number) {
this.b = 2;
return a;
}
const number = new IntNumber(1);
number; // { b: 2 }