instanceof原理

83 阅读1分钟

arr1 --> Array.prototype --> Object.prototype --> null

虚线 --> 表示__proto__

手写

思路: 遍历原型链

function myInstanceof(obj: any, constructor: Function) {
  // 是否是基本数据类型
  if (isBase(obj)) {
    return false;
  }
  // 遍历原型链
  while (obj) {
    if (obj === constructor.prototype) return true;
    obj = obj.__proto__;
  }
  // 原型链上没有
  return false;
}

// 是否是基本数据类型
function isBase(obj: any) {
  if (obj === null) return true;
  if (typeof obj === "object") return false;
  if (typeof obj === "function") return false;
  return true;
}

// 写法2
// 是否是基本数据类型
function isBase(v: any) {
  if (v === null) return true;
  if (v === undefined) return true;
  if (typeof v === "string") return true;
  if (typeof v === "number") return true;
  if (typeof v === "boolean") return true;
  if (typeof v === "bigint") return true;
  if (typeof v === "symbol") return true;

  return false;
}

测试

console.log(myInstanceof({}, Object));
console.log(myInstanceof([], Object));
console.log(myInstanceof([], Array));
console.log(myInstanceof({}, Array));

class Foo {}
const f = new Foo();
console.log(myInstanceof(f, Foo));
console.log(myInstanceof(f, Object));

function fn() {}
console.log(myInstanceof(fn, Function)); 
// 基本数据类型
console.log(myInstanceof(null, Object));
console.log(myInstanceof(undefined, Object));
console.log(myInstanceof("abc", String));
console.log(myInstanceof(100, Number));

new Son() --> Son.prototype=new Father() --> Father.prototype --> Object.prototype --> null

function Father(name, age) {
    this.name = name;
    this.age = age;
}

Father.prototype.work = function () {
    alert("work");
};

function Son(name, age) {
    Father.call(this, name, age);
}

Son.prototype = new Father();
Son.prototype.play = function () {
    alert("play");
};

const jack = new Son("jack", 19);

const res = instanceof_(jack, Father)
console.log(res) // true
graph TD

son --__proto__--> Son.prototype
Son.prototype --__proto__--> father
father --__proto__--> Father.prototype
Father.prototype--__proto__-->Object.prototype
Object.prototype --__proto__--> null