JavaScript typeof 运算符详解:返回值、陷阱与类型检测最佳实践

作者:异步漫步时间:2026-10-30 11:55:23浏览:224

本文深入解析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 的用法总结就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持本站。

作者最新文章