js实现instanceOf

268 阅读1分钟

developer.mozilla.org/zh-CN/docs/…

按照mdn的解释,可以如下实现instanceOf

第一版

function instanceOf(ins, Model) {
    let __proto__ = Object.getPrototypeOf(ins);
    while(__proto__ && __proto__ !== Model.prototype) {
        __proto__ = Object.getPrototypeOf(__proto__);
    }

    return __proto__ === Model.prototype;
}

测试用例

function Person() {}
const p1 = new Person();
instanceOf(p1, Person);

instanceOf(1, Number);
instanceOf('', String);
instanceOf(true, Boolean);
instanceOf([], Array);
instanceOf({}, Object);
instanceOf(function() {}, Function);

instanceOf(1, Object); // 期待是 false
instanceOf(undefined, Object);// 期待是 false
instanceOf(null, Object);// 期待是 false

如果运行了上面的代码,可以看到下面两个失败了

instanceOf(1, Object);
instanceOf(undefined, Object);
instanceOf(null, Object);

instanceOf(1, Object)应该返回false结果返回true,所以应该对形参ins做类型判断,是基础类型则不进入while

第二版

function instanceOf(ins, Model) {
    let __proto__ = Object.getPrototypeOf(ins);
    if (typeof ins !== 'object' || typeof ins !== 'function') {
        return __proto__ === Model.prototype;
    }
    while(__proto__ && __proto__ !== Model.prototype) {
        __proto__ = Object.getPrototypeOf(__proto__);
    }
    return __proto__ === Model.prototype;
}

或者写成这样
function instanceOf(ins, Model) {
    let __proto__ = Object.getPrototypeOf(ins);
    if (typeof ins === 'object' || typeof ins === 'function') {
        while(__proto__ && __proto__ !== Model.prototype) {
            __proto__ = Object.getPrototypeOf(__proto__);
        }
    }

    return __proto__ === Model.prototype;
}

而instanceOf(undefined, Object)和instanceOf(null, Object)失败是因为报错

Uncaught TypeError: Cannot convert undefined or null to object

因此,加上对这两个特殊值的判断

第三版

function instanceOf(ins, Model) {
    if (ins === undefined || ins === null) return false;

    let __proto__ = Object.getPrototypeOf(ins);
    if (typeof ins === 'object' || typeof ins === 'function') {
        while(__proto__ && __proto__ !== Model.prototype) {
            __proto__ = Object.getPrototypeOf(__proto__);
        }
    }

    return __proto__ === Model.prototype;
}

考虑到代码的健壮性应该要对Model做一下类型判断,Model应该是callable的才行,为了代码简洁这里就不加了。