被手写题目问麻了
相信小伙伴面试时不止一次被要求手写实现xxx了,曾经胖头鱼也被问过n次类似问题,其中有一个题目映像比较深刻,
instanceof实现原理
,这篇文章我想和大家一起尝试用至少3种方式实现...
胖头鱼的手写实现仓库(350 star),你要的手写都有噢
https://github.com/qianlongo/fe-handwriting
instanceof
运算符用于检测构造函数的prototype
属性是否出现在某个实例对象的原型链上。MDN上
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
const auto = new Car('Honda', 'Accord', 1998);
console.log(auto instanceof Car);
// expected output: true
console.log(auto instanceof Object);
// expected output: true
关键点:
Fn的prototype
原型、原型链相信大家早就整明白了,这里就不赘述了。
要实现instanceof
本质上只要只要遍历实例对象的原型链,挨个往上查找看是否有与Fn的prototype
相等的原型,直到最顶层Object
还找不到,那么就返回false,否则结果就是true
/**
*
* @param {*} obj 实例对象
* @param {*} func 构造函数
* @returns true false
*/
const instanceOf1 = (obj, func) => {
// 必须是对象或者函数
if (!(obj && ['object', 'function'].includes(typeof obj))) {
return false
}
let proto = Object.getPrototypeOf(obj)
if (proto === func.prototype) {
return true
} else if (proto === null) {
return false
} else {
return instanceOf1(proto, func)
}
}
// 测试
let Fn = function () { }
let p1 = new Fn()
console.log(instanceOf1({}, Object)) // true
console.log(instanceOf1(p1, Fn)) // true
console.log(instanceOf1({}, Fn)) // false
console.log(instanceOf1(null, Fn)) // false
console.log(instanceOf1(1, Fn)) // false
/**
*
* @param {*} obj 实例对象
* @param {*} func 构造函数
* @returns true false
*/
const instanceOf2 = (obj, func) => {
// 必须是对象或者函数
if (!(obj && ['object', 'function'].includes(typeof obj))) {
return false
}
let proto = obj
while (proto = Object.getPrototypeOf(proto)) {
if (proto === func.prototype) {
return true
}
}
return false
}
// 测试
let Fn = function () { }
let p1 = new Fn()
console.log(instanceOf2({}, Object)) // true
console.log(instanceOf2(p1, Fn)) // true
console.log(instanceOf2({}, Fn)) // false
console.log(instanceOf2(null, Fn)) // false
console.log(instanceOf2(1, Fn)) // false
/**
*
* @param {*} obj 实例对象
* @param {*} func 构造函数
* @returns true false
*/
const instanceOf3 = (obj, func) => {
// 必须是对象或者函数
if (!(obj && ['object', 'function'].includes(typeof obj))) {
return false
}
let proto = Object.getPrototypeOf(obj)
// 因为一定会有结束的时候(最顶层Object),所以不会是死循环
while (true) {
if (proto === null) {
return false
} else if (proto === func.prototype) {
return true
} else {
proto = Object.getPrototypeOf(proto)
}
}
}
// 测试
let Fn = function () { }
let p1 = new Fn()
console.log(instanceOf3({}, Object)) // true
console.log(instanceOf3(p1, Fn)) // true
console.log(instanceOf3({}, Fn)) // false
console.log(instanceOf3(null, Fn)) // false
console.log(instanceOf3(1, Fn)) // false