Daily-Question icon indicating copy to clipboard operation
Daily-Question copied to clipboard

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

Open shfshanyue opened this issue 4 years ago • 7 comments

function fakeInstanceOf (instance, parent): Boolean {}

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

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

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

//=> false
fakeInstanceOf('hello', Object)

shfshanyue avatar Aug 08 '21 01:08 shfshanyue

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__
  }
}

shfshanyue avatar Aug 08 '21 02:08 shfshanyue

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

ywang305 avatar Aug 08 '21 03:08 ywang305

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
    }
}

heretic-G avatar Aug 08 '21 06:08 heretic-G

// 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

lizheng0515 avatar Aug 09 '21 01:08 lizheng0515

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;
}

vandvassily avatar Aug 09 '21 07:08 vandvassily

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

if(parentProto===childProto)

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

penghei avatar May 14 '22 17:05 penghei

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

shfshanyue avatar May 15 '22 04:05 shfshanyue

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

ilukemagic avatar Oct 10 '22 01:10 ilukemagic