instanceof 和 typeof 的区别与正确用法

更新日期: 2025-10-26 阅读: 24 标签: 区别

很多前端开发者经常困惑:什么时候该用 instanceof,什么时候该用 typeof?这两个操作符看起来都用于类型检查,但它们的用途和原理完全不同。


快速了解基本语法

instanceof 的语法很简单:

object instanceof Constructor  // 返回 true 或 false

左边是要检查的对象,右边是构造函数。简单说,就是检查对象是否属于某个构造函数的实例。

typeof 的用法更直接:

typeof value  // 返回类型字符串


instanceof 的工作原理:查找原型链

instanceof 的核心是检查对象的原型链。它的工作流程是这样的:

  1. 获取对象的原型:Object.getPrototypeOf(obj)

  2. 获取构造函数的原型属性:Constructor.prototype

  3. 沿着原型链向上查找,直到:

    • 找到匹配的原型 → 返回 true

    • 找到 null 还没有匹配 → 返回 false

代码来模拟这个过程:

function instanceOf(obj, Ctor) {
  if (typeof obj !== 'object' || obj === null) return false;
  let proto = Object.getPrototypeOf(obj);
  while (proto) {
    if (proto === Ctor.prototype) return true;
    proto = Object.getPrototypeOf(proto);
  }
  return false;
}


实际例子理解原型链

假设我们有这样的继承关系:

function Animal() {}
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);

const d = new Dog();

原型链是这样的:

d → Dog.prototype → Animal.prototype → Object.prototype → null

检查结果:

d instanceof Dog      // true,第一层匹配
d instanceof Animal   // true,第二层匹配  
d instanceof Object   // true,第三层匹配
d instanceof Cat      // false,整个链都没有 Cat.prototype


instanceof 的常见问题

1. 原始类型返回 false

"abc" instanceof String   // false
123 instanceof Number     // false
true instanceof Boolean   // false

只有使用 new 创建的包装对象才会返回 true:

new String('abc') instanceof String   // true

2. 跨框架问题

在不同 iframe 或窗口中,相同的构造函数会有不同的原型:

// 在 iframe A 中
const iframeArray = window.frames[0].Array;
const arr = [];
arr instanceof Array           // true
arr instanceof iframeArray     // false

3. 修改 prototype 的影响

function F() {}
const o = new F();
F.prototype = {};     // 修改了原型
console.log(o instanceof F); // false

4. 自定义 instanceof 行为

ES6 引入了 Symbol.hasInstance,可以自定义 instanceof 的行为:

class MyArray {
  static [Symbol.hasInstance](obj) {
    return Array.isArray(obj) && obj.length > 3;
  }
}

[1,2,3,4] instanceof MyArray; // true
[1,2] instanceof MyArray;     // false


instanceof 与 typeof 对比

typeof 结果instanceof 检查说明
[]'object'Arraytypeof 无法区分数组和对象
{}'object'Object同上
new String('')'object'String包装对象
function fn(){}'function'Functiontypeof 能识别函数
null'object'任何都是 falseJavaScript 的历史问题
"hello"'string'String → false原始类型

实际应用:安全的类型检查

检查数组的推荐方法

// 不推荐的方法
const isArray = value => value instanceof Array;

// 推荐的方法
const isArray = value => Array.isArray(value);

Array.isArray() 比 instanceof 更好,因为它:

  • 性能更好

  • 解决跨框架问题

  • 代码意图更清晰

实用的类型检查函数

function getType(value) {
  // 先处理 null
  if (value === null) return 'null';
  
  // 处理其他类型
  const type = typeof value;
  if (type !== 'object') return type;
  
  // 详细的对象类型检查
  if (Array.isArray(value)) return 'array';
  if (value instanceof Date) return 'date';
  if (value instanceof RegExp) return 'regexp';
  
  return 'object';
}


使用建议和最佳实践

1. 基础类型检查用 typeof

// 检查是否是字符串
if (typeof value === 'string') {
  // 处理字符串
}

// 检查是否是函数
if (typeof callback === 'function') {
  callback();
}

2. 对象类型检查用 instanceof

// 检查是否是日期对象
if (value instanceof Date) {
  console.log(value.getFullYear());
}

// 检查是否是自定义类的实例
if (employee instanceof Manager) {
  employee.approveRequest();
}

3. 特殊情况的处理

// 处理 null 和 undefined
if (value == null) {
  // 同时处理 null 和 undefined
}

// 安全的属性访问
if (typeof obj?.property === 'string') {
  // 使用可选链避免错误
}


常见误区避免

不要用 instanceof 检查原始类型

// 错误
if (value instanceof String) {
  // 这只会对 new String('') 返回 true
}

// 正确
if (typeof value === 'string') {
  // 对字符串字面量和 String 对象都有效
}

注意构造函数的变化

function User(name) {
  this.name = name;
}

const user1 = new User('张三');
User.prototype = {};  // 修改原型
const user2 = new User('李四');

console.log(user1 instanceof User); // false
console.log(user2 instanceof User); // true


进阶技巧

实现多重继承检查

class Animal {}
class Flyable {
  static [Symbol.hasInstance](obj) {
    return typeof obj.fly === 'function';
  }
}

class Bird extends Animal {
  fly() {}
}

const bird = new Bird();
console.log(bird instanceof Animal);  // true
console.log(bird instanceof Flyable); // true

安全的类型判断函数

function safeTypeCheck(value, type) {
  if (typeof type === 'function') {
    return value instanceof type;
  }
  
  switch (type) {
    case 'array': return Array.isArray(value);
    case 'null': return value === null;
    case 'undefined': return value === undefined;
    default: return typeof value === type;
  }
}


总结

记住这几个要点:

  1. typeof 用于检查原始类型和函数,返回类型字符串

  2. instanceof 用于检查对象是否是某个构造函数的实例,检查原型链

  3. 原始类型 用 typeof 检查,对象类型用 instanceof 检查

  4. 跨框架 时使用 Array.isArray() 等内置方法

  5. 注意原型修改 对 instanceof 结果的影响

在实际开发中,根据具体需求选择合适的类型检查方法。对于基础类型,typeof 更合适;对于复杂的对象类型,instanceof 更准确。理解它们的原理和差异,能帮助你写出更健壮的代码。

本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!

链接: https://fly63.com/article/detial/13053

AR / MR / VR / XR有什么区别?

VR能让人完全沉浸在虚拟环境中;AR能创建一个叠加在虚拟内容的世界,但不能与真实环境交互; MR则是虚拟与现实的混合体,它能创造出可以与真实环境交互的虚拟物体。最后,XR则是包括三种“现实”(AR,VR,MR)的术语。

详解call bind apply区别/使用场景/es6实现/es3实现

call,apply,bind的区别:apply接收数组 func.apply(obj, [arus]),call一连串参数 func.call(obj, param1, param2....),bind返回一个函数 func.bind(obj,param...)(parms...)

理解screenX,clientX,pageX,offsetX,pageXoffset的区别

event.screenX、event.screenY鼠标相对于用户显示器屏幕左上角的X,Y坐标。标准事件和IE事件都定义了这2个属性,event.clientX、event.clientY鼠标相对于浏览器可视区域的X,Y坐标

css之word-wrap和word-break的区别

对于英文单词,如果有一个连写且长度很长的英文单词,在第一行显示不下的情况下,浏览器默认不会截断显示,而是把这个单词整体挪到下一行。但是当整体挪到下一行还是显示不完全该肿么办呢?

url 、src 、href 的区别

URL统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL

Js插件、 组件、类库、框架的区别

框架和类库等概念的出现都是源于人们对复用的渴望。“不要重复发明轮子”,成了软件界的一句经典名言。从最初的单个函数源代码的复用,到面向对象中类的复用(通常以类库的形式体现)

*.min.js跟*.js的区别

js是JavaScript 源码文件, .min.js是压缩版的js文件。减小体积 .min.js文件经过压缩,相对编译前的js文件体积较小,传输效率快。防止窥视和窃取源代码

PTN与SDH的区别?

SDH是基于TDM技术,主要用于传输语音,此外采用GFP封装来传输IP包,物理介质为光纤。PTN是采用DWDM技术,主要用于传输IP包、以太网帧,此外采用MPLS-TP技术来实现PWE3伪线

html中src与href的区别

写代码的时候就经常把这两个属性弄混淆,到底是href还是src,href表示超文本引用,用在link和a等元素上,href是引用和页面关联,是在当前元素和引用资源之间建立联系,src表示引用资源,表示替换当前元素,用在img,script,iframe上

Js绑定事件的两种方式的区别

运行后发现,点击后src没有变化,调试发现,这里this是window对象,而不是img标签对象。顿时感觉有点迷惑,因为以前绑定事件中,拿标签属性都是用的this,怎么这里不对了?

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!