🎯 一、为什么要掌握这三种类型判断?
在开发和面试中你一定遇到过:
判断方式 | 优点 | 缺点 |
---|---|---|
typeof |
快速判断原始类型 | 对对象不准,如 typeof null === 'object' |
instanceof |
判断引用类型关系 | 对基本类型无效,跨 iframe 不准 |
Object.prototype.toString.call |
最精确的方式 | 写法繁琐,需背模板 |
掌握这些是 JS 基础能力的核心体现,也是面试官常考点。
📌 二、类型判断原理总览
方法 | 原理 | 常见用途 |
---|---|---|
typeof |
内部通过 typeof 操作符返回固定字符串 |
判断基本类型 |
instanceof |
判断 原型链 上是否存在构造函数的 prototype | 判断对象与类的继承关系 |
toString.call() |
利用对象内部的 [[Class]] 值 |
判断所有对象准确类型 |
✍️ 三、手写 instanceof
我们已在第 3 篇中写过,这里复习:
ini
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
是语言级别保留的操作符,不能被完全手写模拟,但可以封装一个更强的类型判断函数来补足它的不足:
javascript
function getType(val) {
return typeof val === 'object'
? val === null
? 'null'
: Object.prototype.toString.call(val).slice(8, -1).toLowerCase()
: typeof val;
}
✅ 示例:
scss
getType(123); // 'number'
getType(null); // 'null'
getType([]); // 'array'
getType(() => {}); // 'function'
getType(Symbol('x')); // 'symbol'
✍️ 五、手写 Object.prototype.toString.call
封装
javascript
function toRawType(val) {
return Object.prototype.toString.call(val).slice(8, -1); // 输出大写首字母格式:Array/Object/Date...
}
示例:
scss
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 |
✅ | ✅ | ✅ | ✅ | ✅ |