instanceof
和 typeof
instanceof
instanceof
用于检查一个对象是否是某个构造函数的实例。换句话说,它会检查对象的原型链上是否存在该构造函数的 prototype
属性。 示例代码
js
let a = new Number(1)
console.log(a instanceof Number); // true
console.log(a.__proto__.constructor === Number) // true
console.log(a.__proto__ === Number.prototype) // true
console.log('------')
let b = 1
console.log(b instanceof Number); // false
console.log(b.__proto__.constructor === Number) // true
console.log(b.__proto__ === Number.prototype) // true (临时包装对象)
按照上面的说法
x instanceof Y
检查 x
的原型链上是否有 Y.prototype
。
可以等效为 x.__proto__ === Y.prototype
(但是又不完全等效,因为instanceof会在整个原型链上递归查找)
如果我们仅看这个简单的等效,对比上面的4、9行代码。
a是对象 ,b是原始类型 。严格来说,原始类型是没有__proto__
的,但是JS引擎会在访问他们的属性的时候,临时包装成对象,使其看起来有__proto__
,所以在第9行,还是会输出 true
所以这里为什么第7行,输出是false呢,不是按照上面的规则来,就检查x.__proto__ === Y.prototype
吗,既然第9行为true,但是第7行为false呢?
这里就涉及到另外一条规则了,如果x是原始类型,那么会直接返回false,因为原始类型没有原型链,上面的第9行是包装之后才有了原型链。
工作原理
x instanceof Y
的完整行为:
- 如果
x
是原始类型(如1
,"a"
,true
),直接返回false
(因为原始类型没有原型链)。 - 如果
x
是对象,则沿着x
的原型链向上查找,检查是否有Y.prototype
:- 先检查
x.__proto__ === Y.prototype
,如果是,返回true
。 - 如果不是,继续检查
x.__proto__.__proto__ === Y.prototype
,依此类推,直到原型链尽头(null
)。
- 先检查
js
class Animal {}
class Dog extends Animal {}
const dog = new Dog();
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true(因为 Dog 继承 Animal)
console.log(dog instanceof Object); // true(所有对象最终继承 Object)
typeof
用来返回变量的基本类型,以字符串的形式返回,且不会检查原型链
js
console.log(typeof 42); // "number"
console.log(typeof "hello"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object"(历史遗留 bug)
console.log(typeof {}); // "object"
console.log(typeof []); // "object"(数组也是对象)
console.log(typeof function() {}); // "function"
console.log(typeof Symbol()); // "symbol"
console.log(typeof 123n); // "bigint"
其中数组、对象、null都会被判断为object。函数也是对象,但是typeof对其进行了特殊处理,返回了function。
typeof null === "object"
这是 JavaScript 早期的一个 Bug,但由于历史原因无法修复。typeof [] === "object"
数组本质是对象,无法直接区分数组和普通对象(可以用Array.isArray()
判断)。typeof function() {} === "function"
函数虽然是对象,但typeof
对其特殊处理,返回"function"
。
总结
操作符 | 适用场景 | 不适用场景 |
---|---|---|
typeof |
检查原始类型、undefined 、function |
无法区分对象的具体类型(如数组 vs 普通对象) |
instanceof |
检查对象是否是某个类的实例(包括继承) | 不适用于原始类型 |
推荐组合使用:
- 先
typeof
判断是否是原始类型。 - 如果是对象,再用
instanceof
或Array.isArray()
进一步判断。