13、✅ 手写 instanceof、typeof、Object.prototype.toString,搞清 JS 类型判断机制

121 阅读1分钟

🎯 一、为什么要掌握这三种类型判断?

在开发和面试中你一定遇到过:

判断方式优点缺点
typeof快速判断原始类型对对象不准,如 typeof null === 'object'
instanceof判断引用类型关系对基本类型无效,跨 iframe 不准
Object.prototype.toString.call最精确的方式写法繁琐,需背模板

掌握这些是 JS 基础能力的核心体现,也是面试官常考点。


📌 二、类型判断原理总览

方法原理常见用途
typeof内部通过 typeof 操作符返回固定字符串判断基本类型
instanceof判断 原型链 上是否存在构造函数的 prototype判断对象与类的继承关系
toString.call()利用对象内部的 [[Class]]判断所有对象准确类型

✍️ 三、手写 instanceof

我们已在第 3 篇中写过,这里复习:

function myInstanceof(obj, Constructor) {
  if (obj == null || typeof obj !== 'object') return false;

  let proto = Object.getPrototypeOf(obj);
  const prototype = Constructor.prototype;

  while (proto) {
    if (proto === prototype) return true;
    proto = Object.getPrototypeOf(proto);
  }

  return false;
}

✅ 四、手写 typeof(本质:操作符,不可完全重写)

typeof 是语言级别保留的操作符,不能被完全手写模拟,但可以封装一个更强的类型判断函数来补足它的不足:

function getType(val) {
  return typeof val === 'object'
    ? val === null
      ? 'null'
      : Object.prototype.toString.call(val).slice(8, -1).toLowerCase()
    : typeof val;
}

✅ 示例:

getType(123); // 'number'
getType(null); // 'null'
getType([]); // 'array'
getType(() => {}); // 'function'
getType(Symbol('x')); // 'symbol'

✍️ 五、手写 Object.prototype.toString.call 封装

function toRawType(val) {
  return Object.prototype.toString.call(val).slice(8, -1); // 输出大写首字母格式:Array/Object/Date...
}

示例:

toRawType([]); // "Array"
toRawType(null); // "Null"
toRawType(new Date()); // "Date"
toRawType(/\d+/); // "RegExp"

🧠 六、对比总结(面试必背)

方法可判断基本类型可判断对象类型可判断数组能准确区分 null跨 iframe 准确性
typeof❌ (typeof null === 'object')
instanceof❌(不同 iframe 的 Array/Function 不一样)
Object.prototype.toString.call