JavaScript类型判断:typeof与Object.prototype.toString详解
本文详解JavaScript中两种主流类型判断方法。首先分析typeof的局限性,指出其对Object、Array等返回object的问题。随后深入讲解Object.prototype.toString.call()的原理,结合ES3与ES5规范对比[[Class]]内部属性的变化,展示如何准确区分Array、Function、Date等复杂类型,并提供最佳实践建议。
typeof 类型判断及其局限性
typeof(param) 用于返回参数 param 的数据类型字符串。
这是 JavaScript 语言内置的全局函数,也是开发者最常用的类型检测手段。其优势在于语法简洁、易于记忆;但主要缺陷在于无法准确区分 object、null、array、regexp 以及自定义对象,这些类型通常都会返回 "object"。
以下代码展示了 typeof 对不同变量的检测结果。
代码如下:
var str='str';
var arr=['1','2'];
var num=1;
var bool=true;
var obj={name:'test'};
var nullObj=null;
var undefinedObj=undefined;
var reg=/reg/;
function fn(){
alert('this is a function');
}
function User(name){
this.name=name;
}
var user=new User('user');
console.log(typeof(str));
console.log(typeof(arr));
console.log(typeof(num));
console.log(typeof(bool));
console.log(typeof(obj));
console.log(typeof(nullObj));
console.log(typeof(undefinedObj));
console.log(typeof(reg));
console.log(typeof(fn));
console.log(typeof(user));运行上述代码后,控制台输出结果如下。
代码如下:
string
object
number
boolean
object
object
undefined
object
function
object2、Object.prototype.toString().call(param) 返回 param 的类型(字符串格式为 [object class])。
Object.prototype.toString 原理与规范演进
该方法能够覆盖绝大多数基础类型的判断,jQuery 库中封装的类型判断逻辑也基于此方法。部分读者可能对后续内容感到困惑,下面我们将逐步拆解其原理。
1)call(param) 函数机制
在 JavaScript 中,a.fun().call(b) 的含义是让对象 b 临时替代对象 a 执行 a 的 fun 函数。通过以下示例进行说明:
代码如下:
function Class1()
{
this.name = "class1";
this.showNam = function()
{
alert(this.name);
}
}
function Class2()
{
this.name = "class2";
}
var c1 = new Class1();
var c2 = new Class2();
c1.showNam.call(c2);运行结果输出 "class2" 而非 "class1",这体现了方法借用或类似继承的效果。
因此,Object.prototype.toString().call(param) 的本质是将 param 作为 this 执行 toString 方法。为什么不直接写 param.prototype.toString()?这是因为普通对象可能没有 prototype 属性或该方法被重写,下面通过第 2 点详细解释。
2)Object.prototype.toString() 的作用
Object 是所有 JavaScript 对象的基类,提供了所有对象通用的功能。根据官方文档(如 Script56.chm),Object 是一个概念性的祖先,所有 JS 对象都是 Object 的实例,但不同对象会重写自己的方法。prototype 属性返回原型的引用,允许动态向原型添加方法和属性。以下是一个简单示例:
代码如下:
function class(){
this.name = "class";
this.showName = function(){
alert(this.name);
}
}
var obj = new class();
obj.showName();
class.prototype.showNameContact = function(){
alert("prototype test"+this.name);
}
obj.showNameContact();上述代码分别输出 "class" 和 "prototype test class"。构造函数 class() 内部并未定义 showNameContact,但通过 prototype 动态添加后,new 出的实例即可调用。因此,Object.prototype.toString() 指的是执行 Object 基类中的 toString 方法。
那么toString()是干嘛的呢?很多js手册中对toString()函数是这样定义的: toString() 方法可把一个逻辑值转换为字符串,并返回结果,语法为:booleanObject.toString()。刚才我说了,js中的对象都是继承的Object,这些对象都自定义的有函数或者重构了Object的部分函数,而且它们都对toString()函数进行了重写。所以我们不能想1中直接写param.prototype.toString()这样就执行的是param自己重写后的toString()函数了。
接下来进入核心部分:toString() 的具体作用及其返回值机制。
在 ES3 规范中,Object.prototype.toString 方法的执行步骤如下:
Object.prototype.toString()
当调用 toString 方法时,执行以下步骤:
1. 获取 this 对象的 [[Class]] 内部属性的值。
2. 将字符串 "[object "、第一步的结果 Result(1) 以及 "]" 连接成新字符串。
3. 返回第二步生成的字符串 Result(2)。
ES3 规范未明确列出 [[class]] 的所有可能值,但统计原生对象的 [[Class]] 内部属性值共有 10 种:"Array", "Boolean", "Date", "Error", "Function", "Math", "Number", "Object", "RegExp", "String"。因此,Object.prototype.toString() 的输出格式为 [object Array]、[object Boolean] 等。
在 ES5.1 规范中,定义更加详细,Object.prototype.toString 方法和 [[Class]] 内部属性的定义有所变化,具体规范如下:
Object.prototype.toString ( ) 当调用 toString 方法时,执行以下步骤:
1. 如果 this 值为 undefined,则返回 "[object Undefined]"。 2. 如果 this 值为 null,则返回 "[object Null]"。 3. 令 O 为调用 ToObject(this) 的结果。 4. 令 class 为 O 的内部属性 [[Class]] 的值。 5. 返回将 "[object "、class 以及 "]" 连接后的新字符串。
与 ES3 相比,ES5.1 增加了第 1、2、3 步。其中第 1、2 步属于新增规则,较为特殊,因为 "Undefined" 和 "Null" 并非 [[class]] 属性的标准值。经统计,可返回的类型包括 "Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", "String"。相比 ES3,新增了两种类型:arguments 对象的 [[Class]] 变为 "Arguments"(此前为 "Object"),以及新增的全局对象 JSON,其 [[Class]] 值为 "JSON"。
最后提醒,Object.prototype.toString().call(param) 返回的 [object class] 中 class 部分首字母大写,如 "JSON" 全大写。为避免大小写敏感问题,建议在判断时将结果转换为小写,即使用 Object.prototype.toString().call(param).toLowerCase()。
JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
JS 解压出现乱码或报错怎么解决?
2026-11-05 12:32:38
JS 中 startsWith、indexOf 与正则判断字符串前缀的对比
2026-11-04 22:19:43
JS解析Excel后怎么将数据转换为JSON格式
2026-11-04 20:58:28
