JavaScript中typeof与instanceof类型判断详解及常见陷阱
本文深入解析JavaScript中typeof和instanceof两种类型判断机制。详细阐述typeof返回字符串的局限性,特别是针对对象、数组和null的处理;介绍利用Object.prototype.toString进行精确类型检测的方法。通过七道典型真题剖析变量提升、this指向、函数声明等底层原理,并探讨instanceof判断构造函数原型链的逻辑及原型覆盖带来的影响。
JavaScript类型判断概述
本次主要探讨JavaScript中用于类型判断的两个核心机制:使用typeof进行基础类型检测,以及利用instanceof检查构造函数原型链的方法,并重点分析在实际应用中的注意事项。
typeof运算符详解
typeof运算符
首先介绍typeof。该运算符返回一个字符串,用于标识操作数的数据类型。
typeof属于一元运算符,置于操作数之前,其操作数可以是任意类型的数据。
该运算符返回一个字符串,说明运算数的类型。typeof通常只能返回以下结果:number、boolean、string、function、object、undefined。我们可以利用typeof来检查变量是否存在,例如 if(typeof a!="undefined"){alert("ok")},而避免直接使用 if(a),因为如果变量a未声明,直接使用会抛出错误。对于Array、Null等特殊对象,typeof一律返回object,这体现了typeof的局限性。
语法说明
首先查看各种数据类型对应的typeof返回值:
| 数据类型 | Type |
|---|---|
| Undefined | “undefined” |
| Null | “object” |
| 布尔值 | “boolean” |
| 数值 | “number” |
| 字符串 | “string” |
| Symbol (ECMAScript 6 新增) | “symbol” |
| 宿主对象(JS环境提供的,比如浏览器) | Implementation-dependent |
| 函数对象 | “function” |
| 任何其他对象 | “object” |
接着看具体的代码示例:
// Numbers
typeof 37 === 'number';
typeof 3.14 === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; // 尽管NaN是"Not-A-Number"的缩写,意思是"不是一个数字"
typeof Number(1) === 'number'; // 不要这样使用!
// Strings
typeof "" === 'string';
typeof "bla" === 'string';
typeof (typeof 1) === 'string'; // typeof返回的肯定是一个字符串
typeof String("abc") === 'string'; // 不要这样使用!
// Booleans
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(true) === 'boolean'; // 不要这样使用!
// Symbols
typeof Symbol() === 'symbol';
typeof Symbol('foo') === 'symbol';
typeof Symbol.iterator === 'symbol';
// Undefined
typeof undefined === 'undefined';
typeof blabla === 'undefined'; // 一个未定义的变量,或者一个定义了却未赋初值的变量
// Objects
typeof {a:1} === 'object';
// 使用Array.isArray或者Object.prototype.toString.call方法可以从基本的对象中区分出数组类型
typeof [1, 2, 4] === 'object';
typeof new Date() === 'object';
// 下面的容易令人迷惑,不要这样使用!
typeof new Boolean(true) === 'object';
typeof new Number(1) ==== 'object';
typeof new String("abc") === 'object';
// 函数
typeof function(){} === 'function';
typeof Math.sin === 'function';
我们会发现一个问题,即使用typeof判断数据类型并不完全准确。例如数组、正则表达式、日期和自定义对象的typeof返回值均为object,这会导致判断误差。
因此,在typeof判断类型的基础上,我们还需要利用Object.prototype.toString方法来进行更精确的数据类型判断。
我们来看看在相同数据类型下,toString方法和typeof方法返回值的区别:
| 数据 | toString | typeof |
|---|---|---|
| “foo” | String | string |
| new String(“foo”) | String | object |
| new Number(1.2) | Number | object |
| true | Boolean | boolean |
| new Boolean(true) | Boolean | object |
| new Date() | Date | object |
| new Error() | Error | object |
| new Array(1, 2, 3) | Array | object |
| /abc/g | RegExp | object |
| new RegExp(“meow”) | RegExp | object |
可以看到,利用toString方法可以正确区分出Array、Error、RegExp、Date等具体类型。
因此,我们通常通过该方法来进行严格的数据类型验证。
typeof实战真题解析
实战检测
既然讨论到了typeof,这里列出几道题目,检验是否真正掌握了typeof的用法。
第一题:
var y = 1, x = y = typeof x;
x;
第二题:
(function f(f){
return typeof f();
})(function(){ return 1; });
第三题:
var foo = {
bar: function() { return this.baz; },
baz: 1
};
(function(){
return typeof arguments[0]();
})(foo.bar);
第四题:
var foo = {
bar: function(){ return this.baz; },
baz: 1
}
typeof (f = foo.bar)();
第五题:
var f = (function f(){ return "1"; }, function g(){ return 2; })();
typeof f;
第六题:
var x = 1;
if (function f(){}) {
x += typeof f;
}
x;
第七题:
(function(foo){
return typeof foo.bar;
})({ foo: { bar: 1 } });
下面公布答案,这七题的答案分别是:
"undefined","number","undefined","undefined","number","1undefined","undefined"
做对了几道呢?是否感到困惑?这几题虽然都涉及typeof,但考察了大量JavaScript基础。下面我们来一一详解。
第一题:
var y = 1, x = y = typeof x;
x;//"undefined"
表达式是从右往左执行的。由于变量提升,x的类型不是null,而是undefined,所以最终x=y="undefined"。
关于变量提升,我在其他文章中有详细提及,可供参考。
第二题:
(function f(f){
return typeof f();//"number"
})(function(){ return 1; });
传入的参数为f,即 function(){ return 1; } 这个函数。通过f()执行后,得到结果1,所以typeof 1返回"number"。这道题比较简单,主要在于区分f和f()。
第三题:
var foo = {
bar: function() { return this.baz; },
baz: 1
};
(function(){
return typeof arguments[0]();//"undefined"
})(foo.bar);
这一题考察的是this的指向。this永远指向函数执行时的上下文,而不是定义时的(ES6的箭头函数除外)。当arguments执行时,this已经指向了window对象。所以结果是"undefined"。对this执行不熟悉的同学可以查看相关文章:深入理解this,对箭头函数感兴趣的同学可以查看初步探究ES6之箭头函数。
第四题:
var foo = {
bar: function(){ return this.baz; },
baz: 1
}
typeof (f = foo.bar)();//undefined
如果上面那一题做对了,那么这一题也应该不会错,同样是this的指向问题。
第五题:
var f = (function f(){ return "1"; }, function g(){ return 2; })();
typeof f;//"number"
这一题比较容易错,因为我在遇到这道题之前也从来没有遇到过javascript的分组选择符。什么叫做分组选择符呢?举一个例子就会明白了:
var a = (1,2,3);
document.write(a);//3,会以最后一个为准
所以上面的题目会返回2,typeof 2当然是"number"啦。
第六题:
var x = 1;
if (function f(){}) {
x += typeof f;
}
x;//"1undefined"
这是一个javascript语言规范上的问题,在条件判断中加入函数声明。这个声明语句本身没有错,也会返回true,但是javascript引擎在搜索的时候却找不到该函数。所以结果为"1undefined"。
第七题:
(function(foo){
return typeof foo.bar;
})({ foo: { bar: 1 } });
这题其实是一个考察心细程度的题目。形参的foo指向的是{ foo: { bar: 1 } }这个整体。相信这么说就明白了。
好啦。上面的题目都是很好的资源。
instanceof运算符与原型链
instanceof运算符
接下来该说说instanceof方法了。instanceof运算符可以用来判断某个构造函数的prototype属性是否存在于另外一个要检测对象的原型链上。
instanceof 用于判断一个变量是否某个对象的实例,如 var a=new Array();alert(a instanceof Array); 会返回 true,同时 alert(a instanceof Object) 也会返回 true;这是因为 Array 是 object 的子类。再如:function test(){};var a=new test();alert(a instanceof test) 会返回
谈到 instanceof 我们要多插入一个问题,就是 function 的 arguments,我们大家也许都认为 arguments 是一个 Array,但如果使用 instaceof 去测试会发现 arguments 不是一个 Array 对象,尽管看起来很像。
如果对原型不太了解,可以看看深入理解原型。
下面我们看看instanceof的实例:
// 定义构造函数
function C(){}
function D(){}
var o = new C();
// true,因为 Object.getPrototypeOf(o) === C.prototype
o instanceof C;
// false,因为 D.prototype不在o的原型链上
o instanceof D;
o instanceof Object; // true,因为Object.prototype.isPrototypeOf(o)返回true
C.prototype instanceof Object // true,同上
C.prototype = {};
var o2 = new C();
o2 instanceof C; // true
o instanceof C; // false,C.prototype指向了一个空对象,这个空对象不在o的原型链上.
D.prototype = new C(); // 继承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true
但是这里我们需要注意一个问题:
function f(){ return f; }
document.write(new f() instanceof f);//false
function g(){}
document.write(new g() instanceof g);//true
第一个为什么返回false呢?因为构造函数的原型被覆盖了,我们可以看看new f和new g的区别:

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
