本文深入解析 JavaScript 中的基本数据类型与引用数据类型,详细对比 typeof、Object.prototype.toString.call()、Array.isArray 及 instanceof 四种类型判断方法的原理与适用场景,并提供封装通用类型判断函数的实战代码,帮助开发者准确处理各种数据类型的识别与转换问题。
前言
你是否清楚 JavaScript 语言中具体包含哪些数据类型?面对各种变量,是否有高效且准确的方法来判断其类型?如果需要进一步实现类型之间的转换,又该如何操作?本文将围绕这三个核心问题展开详细讲解。
数据类型
在 JavaScript 中,数据类型主要划分为两大类:基本数据类型(也称为值类型)和引用数据类型(也称为对象类型)。
基本数据类型包括以下七种:
- number(数值)
- String(字符串)
- boolean(布尔值)
- Null(空值)
- Undefined(未定义)
- BigInt(大整数)
- Symbol(符号)
引用数据类型主要包括:
- Object(普通对象)
- Array(数组)
- Function(函数)
- Date 等内置对象
类型判断
一、typeof 方法
typeof 123 // "number"
typeof 'a' // "string"
typeof true // "boolean"
typeof undefined // "undefined"
typeof Symbol() // "symbol"
typeof 21n // "bigint"

通过上述示例可以总结出一个规律:typeof 方法能够准确判断除 Null 以外的所有基本数据类型。需要注意的是,typeof null 返回 "object",这是 JavaScript 语言早期的一个历史遗留 bug,需要特别记忆。对于其他六种基本数据类型,typeof 均能准确识别,因此我们可以利用 (typeof 变量 === "undefined") 来检查一个变量是否已被声明。然而,在判断引用类型时,typeof 仅能准确识别函数类型,其他所有引用类型(如对象、数组等)均返回 'object'。因此,通常推荐使用 typeof 方法来判断基本数据类型。
二、Object.prototype.toString.call() 方法
使用 Object.prototype.toString.call() 方法时,其返回值格式为 "[object 类型]"(注意:返回值前缀是小写 "object",后缀是首字母大写的类型名称)。
Object.prototype.toString.call(123) // "[object Number]"
Object.prototype.toString.call('abc') // "[object String]"
Object.prototype.toString.call(Symbol()) // "[object Symbol]"
Object.prototype.toString.call(21n) // "[object BigInt]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(true) // "[object Boolean]
由此可见,Object.prototype.toString.call() 方法可以准确判断所有基本数据类型。那么,它对引用数据类型的判断能力如何呢?
Object.prototype.toString.call({a:1}) // "[object Object]"
Object.prototype.toString.call([1,2]) // "[object Array]"
Object.prototype.toString.call(new Date) // "[object Date]"
Object.prototype.toString.call(function(){}) // "[object Function]"
Object.prototype.toString.call(new Error()) // "[object Error]"
Object.prototype.toString.call(/a/g) // "[object RegExp]"--正则表达式
Object.prototype.toString.call(Math) // "[object Math]"
Object.prototype.toString.call(JSON) // "[object JSON]"
实际上,Object.prototype.toString.call() 方法能够识别 JavaScript 中所有的数据类型。需要说明的是,示例中出现的 Math 属性和正则表达式严格意义上不属于独立的数据类型,但由于该方法也能识别它们,因此一并列入示例中。
小插曲
如何利用上述两种方法优雅地封装一个函数,使其接收任意数据并直接返回其数据类型(以小写字符串形式)?
方法一:
function dataType(obj) {
return Object.prototype.toString.call(obj).slice(8,-1)
}

方法二:
let dataType = {}
['Boolean', 'Number', 'String', 'Array', 'Function', 'Date', 'RegExp', 'Object',
'Error', 'Undefined', 'Null'].map((item, index) => {
dataType["[object" + item + "]"] = item.toLowerCase();
})
function type(obj) {
return typeof obj === 'object' || typeof obj === 'function'
? dataTypeObject.prototype.toString.call(obj)]
|| 'object' : typeof obj
}
接下来我们解读方法二。首先,我们将所有数据类型名称的首字母转换为小写,并将其作为属性添加到自定义的 dataType 对象中(利用 toLowerCase() 方法将字符串转换为小写)。
当传入一个数据时,首先使用 typeof 判断其是基本类型还是引用类型。由于 typeof null 返回 'object',因此我们的判定条件设为 typeof obj === 'object' || typeof obj === 'function',从而将特殊的 null 视为引用类型处理。这样,使用 Object.prototype.toString.call() 方法也能正确识别,从而实现预期的效果。
(在学习过程中,我们应尽可能将问题复杂化,以加深理解。虽然方法二逻辑更复杂,但方法一的实用性较大。)
三、Array.isArray()
数组提供了一种 isArray 方法,用于判断数据是否为数组类型,返回值是布尔类型(true 或 false)。在其他编程语言中,arr2 = [1, 'abc', true] 严格意义上可能不被视为标准数组,但在 JavaScript 中,这属于合法的数组定义。

四、obj instanceof Object
instanceof 运算符用于判断左侧的操作数是否为右侧构造函数 prototype 属性所指向的原型链上的实例。它只能用于判断复杂数据类型(引用类型),因为它是通过检测构造函数(右侧)的 prototype 属性是否出现在实例对象(左侧)的原型链上来工作的。
[1,2] instanceof Array // true
(function(){}) instanceof Function // true
({a:1}) instanceof Object // true
(new Date) instanceof Date // true
实现原理:
function instance_of(L,R){
let O = R.prototype
let L = L.__proto__
while(L !== null){
if(L === O) return true
L = L.__proto__
}
return false
}
obj instanceof Object方法也可以判断内置对象。
结语
以上就是本期关于 JavaScript 数据类型及其判断方法的全部内容。相信此时,你已经能够轻松应对 JavaScript 中的类型判断问题。虽然判断数据类型的方法不止这些,但上述几种方法(理论上)足以解决所有数据类型的判断需求。
以上就是 JS 疑惑的数据类型及类型判断方法详解的详细内容,更多关于 JS 数据类型判断的资料请关注本站其它相关文章!