引言
在 JS
编程中, 正确判断数据类型是必备技能, 也是面试常问的内容。本文将探讨 四种
常用的数据类型判断方法:
-
typeof
-
instanceof & isPrototypeOf()
-
constructor
-
Object.prototype.toString.call()
通过了解它们的特点和适用范围, 能够更好地处理不同数据类型的情况, 避免出现错误和提升代码质量
一、typeof
typeof
运算符返回一个字符串, 表示操作数的类型, 使用语法:typeof <操作数>
1.1 规则
下表, 是 typeof
针对不同数据类型, 返回的结果值
类型 | 结果 |
---|---|
Boolean | "boolean " |
String | "string " |
Number | "number " |
BigInt | "bigint " |
Symbol | "symbol " |
Undefined | "undefined " |
Null | "object " |
Function (在 class 也是函数) | "function " |
其他任何对象 | "object " |
示例代码如下:
console.log(typeof true)
console.log(typeof '123')
console.log(typeof 11111)
console.log(typeof Math.LN2)
console.log(typeof Infinity)
console.log(typeof NaN)
console.log(typeof BigInt(11111))
console.log(typeof Symbol(1111))
console.log(typeof undefined)
console.log(typeof null)
console.log(typeof (() => {}))
console.log(typeof class {})
console.log(typeof {})
console.log(typeof [])
console.log(typeof /abc/)
console.log(typeof new Date())
console.log(typeof new Promise(() => {}))
1.2 为什么「typeof null」等于「object」
typeof null === "object";
-
在
JS
中typeof null
的结果为"object"
, 这是从JS
的第一版遗留至今的一个bug
-
在
JS
最初的实现中,JS
中的值是由一个表示类型的标签
和实际数据值
表示的, 对象的类型标签
是0
, 由于null
代表的是空指针, 在大多数平台下值表示为0x00
, 因此,null
的类型标签
是0
, 因此typeof null
也就返回了object
-
当然针对这个
BUG
曾有一个ECMAScript
的修复提案, 但是被拒绝了, 原因是遗留代码太多了, 如果修改的话影响太广, 不如继续将错就错当个和事老
1.3 为什么「typeof (() => {})」等于 「function」
首先我们需要了解一个小知识, 函数是什么? 为什么被调用?
function
实际上是 object
的一个 子类型
, 更深点说, 函数是一个可以被调用的对象; 那么它为什么能够被调用呢? 那是因为其内部实现了 [[Call]]
方法, 当函数对象被调用时会执行内部方法 [[call]]
那么回到正题, 为什么 typeof (() => {})
会返回 function
? 这里主要还是要看 ES6
中 typeof
是如何区分函数和对象类型的:
-
一个对象如果没有实现
[[Call]]
内部方法, 那么它就返回object
-
一个对象如果实现了
[[Call]]
内部方法, 那么它就返回function
1.4 注意事项
-
所有使用
构造函数
创建的数据,typeof
都会返回object
或function
const str = new String("String");
const num = new Number(100);
typeof str;
typeof num;
const func = new Function();
typeof func;
-
typeof
操作符的优先级高于加法 (+)
等二进制操作符
, 因此, 必要时候记得用括号
const someData = 99;
typeof someData + " Wisen";
typeof (someData + " Wisen");
二、instanceof & isPrototypeOf()
在 JS
中我们有 两种
方式可以判断 原型
是否存在于某个 实例
的 原型链
上, 通过这种判断就可以帮助我们, 确定 引用数据
的具体类型; 需要注意的是该方法 只能用于判断引用数据
, 无法判断 基本数据
类型
2.1 instanceof
-
介绍:
instanceof
运算符用于检测构造函数
的prototype
属性是否出现在某个实例
对象的原型链
上 -
语法:
实例对象 instanceof 构造函数
, 返回一个Boolean
值 -
示例:
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
const auto = new Car('Honda', 'Accord', 1998);
auto instanceof Car
auto instanceof Object
2.2 Object.prototype.isPrototypeOf()
-
介绍:
isPrototypeOf()
方法用于检查一个对象
是否存在于另一个对象
的原型链中 -
语法:
原型.isPrototypeOf(实例)
, 返回一个布尔值 -
示例:
function Car() {}
const auto = new Car();
Car.prototype.isPrototypeOf(auto)
Object.prototype.isPrototypeOf(auto)
三、根据「constructor」进行判断
constructor
判断方法跟 instanceof
相似, 如下图是 原型
、实例
、构造函数
之间的一个关系图, 从图可知, 在 实例对象的原型
中存在 constructor
指向 构造函数
, 那么借用这个特性我们可以用于判断 数据
类型
function Car() {}
const auto = new Car();
auto.constructor === Car
不同于 instanceof
, 通过该方式既可以处理 引用数据
、又能够处理 基本数据
(123).constructor === Number
(true).constructor === Boolean
('bar').constructor === String
不同于 instanceof
, 不能判断 对象父类
class A {}
class B extends A {}
const b = new B()
b.constructor === B
b.constructor === A
b instanceof B
b instanceof A
注意: null
和 undefined
没有 constructor
, 所以它是无法检测 Null
undefined
四、Object.prototype.toString.call()
Object.prototype.toString.call()
方法返回一个表示该对象的字符串, 该字符串格式为 "[object Type]"
, 这里的 Type
就是对象的类型
const toString = Object.prototype.toString;
toString.call(111);
toString.call(null);
toString.call(undefined);
toString.call(Math);
toString.call(new Date());
toString.call(new String());
注意: 对于自定义构造函数实例化出来的对象, 返回的是 [object Object]
const toString = Object.prototype.toString;
function Bar(){}
toString.call(new Bar());
默认, 如果一个对象有 Symbol.toStringTag
属性并且该属性值是个字符串, 那么这个属性值, 会被用作 Object.prototype.toString()
返回内容的 Type
值进行展示
const toString = Object.prototype.toString;
const obj = {
[Symbol.toStringTag]: 'Bar'
}
toString.call(obj)
补充: 一个通用方法, 一行代码获取 数据的类型
const getType = (data) => {
return Object.prototype.toString.call(data)
.slice(8, -1)
.toLocaleLowerCase()
}
五、总结
判断方法 | 基本类型 | 引用类型 | 父类 | null | undefined |
---|---|---|---|---|---|
typeof | ✅ | ❌ | ❌ | ❌ | ✅ |
instanceof & isPrototypeOf() | ❌ | ✅ | ✅ | ❌ | ❌ |
constructor | ✅ | ✅ | ❌ | ❌ | ❌ |
Object.prototype.toString.call() | ✅ | ✅ | ❌ | ✅ | ✅ |
-
typeof
适合用于判断基本类型
, 特别的是:Null
会返回object
、Function
返回function
、其余引用类型
都返回object
-
instanceof & isPrototypeOf()
可以用于判断引用数据的类型, 同时可判断对象父类
-
constructor
可用于基本类型、引用类型, 但是不可判断null
、undefined
, 并且无法判断对象父类
-
Object.prototype.toString.call()
万能方法, 对于JS
中所有类型都能够识别出来, 唯一不足的可能是无法判断对象父类
(但是问题不大)
作者-墨渊君,欢迎关注!
so
-
结尾依旧:长风破浪会有时,直挂云帆济沧海!
-
在线整理的确实很好,对文章进行了一个汇总整理,在线备战面试、刷题指南,拿走不谢,要学会站在别人的肩膀上提升自己点击这里-->
最后:
如果你现在正在找工作,可以私信“web”或者直接添加下方小助理进群领取前端面试小册、简历优化修改、大厂内推以及更多阿里、字节大厂面试真题合集,和p8大佬一起交流。