面试题:JavaScript 如何判断一个对象是否属于某个类?

在 JavaScript 中,判断一个对象是否属于某个类(或更准确地说,是否由某个构造函数创建或在其原型链上)有多种方法,各有优缺点和适用场景。


1. instanceof 操作符

  • 作用:检查一个对象在其原型链中是否存在指定构造函数的 prototype 属性。
  • 语法object instanceof Constructor
  • 优点:最常用、最直接的方法,适用于大多数继承场景。
  • 缺点
    • 多个全局执行环境(如 iframe)中可能失效,因为不同环境中的构造函数是不同的对象。
    • 不能用于判断原始类型(如字符串、数字),但可以用于它们的包装对象。
  • 示例
class Animal {}
  class Dog extends Animal {}

  const dog = new Dog();

  console.log(dog instanceof Dog);     // true
  console.log(dog instanceof Animal);  // true (因为继承)
  console.log(dog instanceof Object);  // true (所有对象都继承自 Object)

  const arr = [1, 2, 3];
  console.log(arr instanceof Array);   // true

2. Object.prototype.isPrototypeOf()

  • 作用:检查一个对象是否在另一个对象的原型链中。
  • 语法Constructor.prototype.isPrototypeOf(object)
  • 优点:与 instanceof 类似,但更明确地操作原型链。不受多个全局环境的影响(如果你能正确访问到目标原型)。
  • 缺点:语法稍显繁琐。
  • 示例
class Animal {}
  const dog = new Animal();

  console.log(Animal.prototype.isPrototypeOf(dog)); // true
  console.log(Object.prototype.isPrototypeOf(dog)); // true

3. constructor 属性

  • 作用:检查对象的 constructor 属性是否指向指定的构造函数。
  • 语法object.constructor === Constructor
  • 缺点
    • 非常不可靠constructor 属性可以被轻易修改。
    • 如果对象的原型被完全替换(如 obj.__proto__ = nullObject.create(null)),constructor 可能不存在或不准确。
  • 示例(展示其不可靠性):
function Person(name) {
    this.name = name;
  }

  const person = new Person("Alice");

  console.log(person.constructor === Person); // true (初始状态)

  // 但可以被修改
  person.constructor = Array;
  console.log(person.constructor === Person); // false (错误!)

4. Object.prototype.toString.call()

  • 作用:获取对象的内部 [[Class]] 标签(在 ES6 之后是 @@toStringTag),返回一个标准格式的字符串,如 [object Array][object Date]
  • 语法Object.prototype.toString.call(object) === '[object Type]'
  • 优点
    • 最可靠的方法之一,可以准确判断内置对象类型(如 Array, Date, RegExp, Error 等)。
    • 不受原型链修改的影响。
    • 在多个全局环境中也有效。
  • 缺点:主要用于内置对象,对于自定义类,返回的是 [object Object],无法区分具体是哪个类。
  • 示例
const arr = [1, 2, 3];
  const date = new Date();
  const regex = /abc/;

  console.log(Object.prototype.toString.call(arr));    // '[object Array]'
  console.log(Object.prototype.toString.call(date));   // '[object Date]'
  console.log(Object.prototype.toString.call(regex));  // '[object RegExp]'

  // 用于判断数组(比 instanceof 更可靠)
  console.log(Object.prototype.toString.call(arr) === '[object Array]'); // true

5. Array.isArray()

  • 作用:专门用于判断一个值是否为数组。
  • 优点:是判断数组的推荐方法,比 instanceoftoString 更语义化,且在所有环境下都可靠。
  • 示例
console.log(Array.isArray([1, 2, 3])); // true
  console.log(Array.isArray('not an array')); // false

总结与推荐

场景推荐方法
判断自定义类或继承关系instanceof
判断内置对象类型(如 Array, Date)Array.isArray() (数组) 或 Object.prototype.toString.call()
需要在多个全局环境(iframe)中判断Object.prototype.toString.call()
检查原型链中是否存在某个原型isPrototypeOf()

关键点

  • instanceof 是判断类实例的首选。
  • constructor 不要依赖
  • 对于数组,优先使用 Array.isArray()
  • Object.prototype.toString.call() 是判断内置对象类型的“核武器”,非常可靠。
THE END
喜欢就支持一下吧
点赞12 分享