JavaScript typeof 运算符详解:返回值、陷阱与类型检测最佳实践
本文深入解析JavaScript中typeof运算符的用法、返回值及常见陷阱。重点探讨typeof返回字符串的特性,分析未声明变量检测、null被识别为object的历史遗留问题,以及区分原始值与对象值的最佳实践。通过对比instanceof与Object.create(null)等场景,提供isDefined、isObject等实用检测函数的实现方案,帮助开发者更准确地处理类型判断。
typeof 运算符基础与返回值
1、作用:
typeof 运算符用于返回表示表达式数据类型的字符串。其可能的返回值包括:"number"、"string"、"boolean"、"object"、"function" 以及 "undefined"。
2、常用返回值说明
typeof 返回值对照表
| 表达式 | 返回值 |
| typeof undefined | 'undefined' |
| typeof null | 'object' |
| typeof true | 'boolean' |
| typeof 123 | 'number' |
| typeof "abc" | 'string' |
| typeof function() {} | 'function' |
| typeof {} | 'object' |
| typeof [] | 'object' |
| typeof unknownVariable | 'undefined' |
需要注意,类型的返回值均为字符串,且首字母始终小写。
3、常规应用:
检测变量存在性与未声明变量处理
1).检查一个变量是否存在,以及是否有值。
在两种情况下,typeof 会返回 "undefined":一是变量尚未被声明,二是变量的值确实为 undefined。例如:
typeof undeclaredVariable === "undefined" true
var declaredVariable;
typeof declaredVariable 'undefined'
typeof undefined 'undefined' 此外,还有其他方法可以检测某个值是否为 undefined:
var value = undefined;
value === undefined true 然而,如果尝试使用严格相等(===)来检测一个未声明的变量,将会抛出异常。只有 typeof 能够在不报错的前提下正常检测未声明的变量:
undeclaredVariable === undefined ReferenceError: undeclaredVariable is not defined 需要注意的是,未初始化的变量、未传入参数的形参以及不存在的属性,都不会出现上述问题,因为它们始终是可访问的,且值始终为 undefined:
var declaredVariable;
declaredVariable === undefined true
(function (x) { return x === undefined }()) true
({}).foo === undefined true 因此,如果想检测一个可能未被声明的全局变量是否存在,也可以使用 if(window.maybeUndeclaredVariable){} 这种写法。
问题: typeof 在执行此类任务时显得较为繁琐。
解决办法: 由于这类操作并不常见,许多人认为无需寻找更优解。不过,或许有人会提出一个专门的操作符:
defined undeclaredVariable false
var declaredVariable;
defined declaredVariable false 或者,也许有人还需要一个用于检测变量是否已被声明的操作符:
declared undeclaredVariable false
var declaredVariable;
declared declaredVariable true 译者注:在 Perl 语言中,上述 defined 操作符相当于 defined(),而 declared 操作符相当于 exists()。
处理 null 被识别为 object 的陷阱
2.判断一个值不等于 undefined 也不等于 null
问题: 如果你想检测一个值是否已被定义(即值既不是 undefined 也不是 null),那么你会遇到 typeof 最著名的怪异表现(常被视为 bug):typeof null 返回了 "object":
typeof null 'object' 注:这只能归因于早期 JavaScript 实现的 bug,而现行标准依然如此规定。V8 引擎曾尝试修正并实现 typeof null === "null",但最终证明不可行。http://wiki.ecmascript.org/doku.php?id=harmony:typeof_null
解决办法: 不要使用 typeof 来执行此项任务,改用以下方法替代。但需注意,变量 x 必须事先声明,否则将报错。
function isDefined(x) { return x !== null && x !== undefined; }
另一种可能性是引入一个“默认值运算符”,当 myValue 未定义时,以下表达式将返回 defaultValue:
myValue || defaultValue 上述表达式等价于:
(myValue !== undefined && myValue !== null) ? myValue : defaultValue
这实际上是下面这条语句的简化形式:
myValue = myValue || defaultValue
区分对象值与原始值的最佳实践
3.区分对象值和原始值
以下函数用于检测 x 是否是一个对象值:
function isObject(x) { return (typeof x === "function" || (typeof x === "object" && x !== null)); } 问题: 上述检测较为复杂,原因在于 typeof 将函数和对象视为不同类型,且 typeof null 返回 "object"。
解决办法: 以下方法也常用于检测对象值:
function isObject2(x) { return x === Object(x); } 警告: 你可能认为这里可以使用 instanceof Object 来检测,但 instanceof 是通过使用一个对象的原型来判断实例关系的。那么,没有原型的对象该如何处理呢:
var obj = Object.create(null);
Object.getPrototypeOf(obj) null obj 确实是一个对象,但它不是任何值的实例:
typeof obj 'object'
obj instanceof Object false 在实际开发中,你可能很少遇到这样的对象,但它确实存在,并有其特定用途。
译者注:Object.prototype 就是一个默认存在的、没有原型的对象。
Object.getPrototypeOf(Object.prototype) null
typeof Object.prototype 'object'
Object.prototype instanceof Object false
获取原始值类型与函数检测
4.原始值的类型是什么?
typeof 是查看某个原始值类型的最佳方式。
typeof "abc" 'string'
typeof undefined 'undefined' 问题: 你必须知晓 typeof null 的怪异表现。
typeof null // 要小心! 'object'
解决办法: 以下函数可以修复此问题(仅针对此用例)。
function getPrimitiveTypeName(x) {
var typeName = typeof x;
switch(typeName) {
case "undefined": case "boolean": case "number": case "string": return typeName;
case "object": if (x === null) { return "null"; }
default: // 前面的判断都没通过 throw new TypeError("参数不是一个原始值: "+x);
} }
更好的解决办法: 实现一个函数 getTypeName(),除了可以返回原始值的类型,还可以返回对象值的内部 [[Class]] 属性。这里讲了如何实现这个函数(译者注:jQuery 中的 $.type 就是这样的实现)。
5.某个值是否是函数
typeof 可用于检测一个值是否为函数。
typeof function () {} 'function'
typeof Object.prototype.toString 'function'
原则上,instanceof Function 也可以进行此类检测。乍一看,这种写法似乎更加优雅。但是,浏览器存在一个怪癖:每个框架和窗口都有它自己的全局变量。因此,如果你将某个框架中的对象传递到另一个框架中,instanceof 就无法正常工作,因为这两个框架拥有不同的构造函数。这就是为什么 ECMAScript 5 中会引入 Array.isArray() 方法的原因。如果存在一种能够跨框架检测对象是否为指定构造函数实例的方法,那将非常理想。上述的 getTypeName() 是一种可用的变通方法,但或许还有更根本的解决方案。
总结:typeof 的局限性与替代方案
6.综述
以下提到的功能,应该是目前 JavaScript 中最迫切需要的,可以替代 typeof 目前承担的部分职责:
isDefined() (例如 Object.isDefined()): 可以作为函数或者一个运算符 isObject() getTypeName() 能够跨框架地检测一个对象是否是指定的构造函数的实例的机制 检查某个变量是否已经被声明这样的需求,可能没那么必要拥有自己的运算符。
以上这篇 js 中判断变量类型函数 typeof 的用法总结就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持本站。
D3.js 比例尺与坐标轴的配置详解
2026-11-05 16:54:46
JavaScript怎么遍历对象的Symbol键和不可枚举属性
2026-11-05 13:13:39
封装一个健壮的JS字符串判空工具函数
2026-11-05 12:16:14
JavaScript合并数组的三种常用方法:concat、扩展运算符与push
2026-11-05 11:22:29
JavaScript立即执行函数(IIFE)是什么及基本语法
2026-11-05 10:51:19
