shfshanyue / Daily-Question

互联网大厂内推及大厂面经整理,并且每天一道面试题推送。每天五分钟,半年大厂中
https://q.shanyue.tech
4.92k stars 508 forks source link

【Q689】JS 中如何原生实现 instanceOf #710

Open shfshanyue opened 3 years ago

shfshanyue commented 3 years ago
function fakeInstanceOf (instance, parent): Boolean {}

//=> true
fakeInstanceOf([], Array)

//=> true
fakeInstanceOf([], Object)

//=> true
fakeInstanceOf(x => x, Object)

//=> false
fakeInstanceOf('hello', Object)
shfshanyue commented 3 years ago
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__
  }
}
ywang305 commented 3 years ago
function fakeInstanceOf (instance, parent) {
  if(! instance?.__proto__ ||  ! parent.prototype) return false;
  if( instance.__proto__ === parent.prototype ) return true;
  return fakeInstanceOf(instance, parent.prototype
}
heretic-G commented 3 years ago
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
    }
}
lizheng0515 commented 3 years ago
// 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
vandvassily commented 3 years ago
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;
}
penghei commented 2 years ago

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

if(parentProto===childProto)

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

shfshanyue commented 2 years ago

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

AlanReumy commented 1 year ago

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