高级前端
手写代码
【Q689】JS 中如何原生实现 instanceOf

JS 中如何原生实现 instanceOf

更多描述

function fakeInstanceOf (instance, parent): Boolean {}
 
//=> true
fakeInstanceOf([], Array)
 
//=> true
fakeInstanceOf([], Object)
 
//=> true
fakeInstanceOf(x => x, Object)
 
//=> false
fakeInstanceOf('hello', Object)

Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 710 (opens in a new tab)

Author 回答者: shfshanyue (opens in a new tab)

function fakeInstanceOf(instance, parent) {
  if (typeof instance !== "object" && typeof instance !== "function") {
    return false;
  }
  let proto = instance?.__proto__ || null;
  while (true) {
    if (proto === null) {
      return false;
    }
    if (proto === parent.prototype) {
      return true;
    }
    proto = proto.__proto__;
  }
}

Author 回答者: ywang305 (opens in a new tab)

function fakeInstanceOf (instance, parent) {
  if(! instance?.__proto__ ||  ! parent.prototype) return false;
  if( instance.__proto__ === parent.prototype ) return true;
  return fakeInstanceOf(instance, parent.prototype
}

Author 回答者: heretic-G (opens in a new tab)

function typeObj(val) {
  if ((typeof val === "function" || typeof val === "object") && val !== null) {
    return true;
  } else {
    return false;
  }
}
 
function instanceOf(left, right) {
  if (!typeObj(right)) {
    throw new Error("error info");
  }
  let hasInstance = right[Symbol.hasInstance];
  if (hasInstance !== undefined && typeof hasInstance === "function") {
    return !!hasInstance.call(right, left);
  } else {
    if (typeof right !== "function") {
      throw new Error("error info");
    }
    if (!typeObj(left)) return false;
    let proto = right.prototype;
    if (!typeObj(proto)) throw new Error("error Info");
    let leftProto = left.prototype;
    while (leftProto !== null) {
      if (leftProto === proto) return true;
      leftProto = leftProto.prototype;
    }
    return false;
  }
}

Author 回答者: lizheng0515 (opens in a new tab)

// left instanceof right
function _instanceof(left, right) {
  // 构造函数原型
  const prototype = right.prototype;
  // 实列对象属性,指向其构造函数原型
  left = left.__proto__;
  // 查实原型链
  while (true) {
    // 如果为null,说明原型链已经查找到最顶层了,真接返回false
    if (left === null) {
      return false;
    }
    // 查找到原型
    if (prototype === left) {
      return true;
    }
    // 继续向上查找
    left = left.__proto__;
  }
}
 
const str = "abc";
_instanceof(str, String); // true

Author 回答者: vandvassily (opens in a new tab)

function fakeInstanceOf(left, right) {
  if (!left) return false;
  if (typeof left !== "object" && typeof left !== "function") return false;
  let proto = left.__proto__;
  const prototype = right.prototype;
 
  while (proto) {
    if (proto === prototype) {
      return true;
    }
    proto = proto.__proto__;
  }
 
  return false;
}

Author 回答者: penghei (opens in a new tab)

有一个小问题问一下大家 代码中判断当前对象是否等于函数prototype的方法是直接用相等判断,即类似这样:

if(parentProto===childProto)

但是有个问题就是,不管是函数的prototype还是对象的__proto__,实际上都是对象,对象之间为什么能用===判断相等?

Author 回答者: shfshanyue (opens in a new tab)

@penghei 因为他们是同一个对象啊

Author 回答者: Awalter0411 (opens in a new tab)

@penghei 因为他们指向同一个对象