typeof

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.

typeof 运算符返回一个字符串,表示操作数的类型。

尝试一下

语法

js
typeof operand

参数

operand

表示要返回类型的对象或基本类型的表达式。

描述

下表总结了 typeof 可能的返回值。有关类型和基本类型的更多信息,可查看 JavaScript 数据结构 页面。

类型 结果
Undefined "undefined"
Null "object"原因
Boolean "boolean"
Number "number"
BigInt "bigint"
String "string"
Symbol "symbol"
Function(在 ECMA-262 中实现 [[Call]];classes也是函数) "function"
其他任何对象 "object"

这个值列表是详尽的。没有符合规范的引擎曾被报告过产生(或历史上产生过)除列出的值之外的值。在规范删除 typeof 为不可调用的非标准外来对象返回实现定义的字符串的行为之前,旧的 Internet Explorer 是已知的唯一一个实现额外返回值的浏览器。

示例

基本用法

js
// 数值
typeof 37 === "number";
typeof 3.14 === "number";
typeof 42 === "number";
typeof Math.LN2 === "number";
typeof Infinity === "number";
typeof NaN === "number"; // 尽管它是 "Not-A-Number" (非数值) 的缩写
typeof Number(1) === "number"; // Number 会尝试把参数解析成数值
typeof Number("shoe") === "number"; // 包括不能将类型强制转换为数字的值

typeof 42n === "bigint";

// 字符串
typeof "" === "string";
typeof "bla" === "string";
typeof `template literal` === "string";
typeof "1" === "string"; // 注意内容为数字的字符串仍是字符串
typeof typeof 1 === "string"; // typeof 总是返回一个字符串
typeof String(1) === "string"; // String 将任意值转换为字符串,比 toString 更安全

// 布尔值
typeof true === "boolean";
typeof false === "boolean";
typeof Boolean(1) === "boolean"; // Boolean() 会基于参数是真值还是虚值进行转换
typeof !!1 === "boolean"; // 两次调用 !(逻辑非)运算符相当于 Boolean()

// Symbols
typeof Symbol() === "symbol";
typeof Symbol("foo") === "symbol";
typeof Symbol.iterator === "symbol";

// Undefined
typeof undefined === "undefined";
typeof declaredButUndefinedVariable === "undefined";
typeof undeclaredVariable === "undefined";

// 对象
typeof { a: 1 } === "object";

// 使用 Array.isArray 或者 Object.prototype.toString.call
// 区分数组和普通对象
typeof [1, 2, 4] === "object";

typeof new Date() === "object";
typeof /regex/ === "object";

// 下面的例子令人迷惑,非常危险,没有用处。避免使用它们。
typeof new Boolean(true) === "object";
typeof new Number(1) === "object";
typeof new String("abc") === "object";

// 函数
typeof function () {} === "function";
typeof class C {} === "function";
typeof Math.sin === "function";

typeof null

js
// JavaScript 诞生以来便如此
typeof null === "object";

在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 "object"。(参考来源

曾有一个 ECMAScript 的修复提案(通过选择性加入的方式),但被拒绝了。该提案会导致 typeof null === 'null'

使用 new 操作符

所有使用 new 调用的构造函数都将返回非基本类型("object""function")。大多数返回对象,但值得注意的例外是 Function,它返回一个函数。

js
const str = new String("String");
const num = new Number(100);

typeof str; // "object"
typeof num; // "object"

const func = new Function();

typeof func; // "function"

语法中需要圆括号

typeof 操作符的优先级高于加法(+)等二进制操作符。因此,需要用括号来计算加法结果的类型。

js
// 括号有无将决定表达式的类型。
const someData = 99;

typeof someData + " Wisen"; // "number Wisen"
typeof (someData + " Wisen"); // "string"

与未声明和未初始化变量的交互

typeof 通常总是保证为它提供的任何操作数返回一个字符串。即使使用未声明的标识符,typeof 也会返回 "undefined",而不是抛出错误。

js
typeof undeclaredVariable; // "undefined"

但在加入了块级作用域的 letconst 之后,在其被声明之前对块中的 letconst 变量使用 typeof 会抛出一个 ReferenceError。块作用域变量在块的头部处于“暂存死区”,直至其被初始化,在这期间,访问变量将会引发错误。

js
typeof newLetVariable; // ReferenceError
typeof newConstVariable; // ReferenceError
typeof newClass; // ReferenceError

let newLetVariable;
const newConstVariable = "hello";
class newClass {}

document.all 的异常行为

当前所有浏览器都公开了一个类型为 undefined 的非标准宿主对象 Document.All

js
typeof document.all === "undefined";

虽然 document.all 也是假值,与 undefined 非严格相等,但它不是 undefined。在 Web 标准中,document.all 具有 "undefined" 类型的情况被归类为“故意违反”原始 ECMAScript Web 兼容性标准。

获取具体类型的自定义方法

typeof 是非常有用的,但它不像需要的那样万能。例如,typeof []"object",以及 typeof new Date()typeof /abc/ 等。

为了更明确地检查类型,这里我们提供了一个自定义的 type(value) 函数,它主要模仿 typeof 的行为,但对于非基本类型(即对象和函数),它在可能的情况下返回更详细的类型名。

js
function type(value) {
  if (value === null) {
    return "null";
  }
  const baseType = typeof value;
  // 基本类型
  if (!["object", "function"].includes(baseType)) {
    return baseType;
  }

  // Symbol.toStringTag 通常指定对象类的“display name”
  // 它在 Object.prototype.toString() 中使用。
  const tag = value[Symbol.toStringTag];
  if (typeof tag === "string") {
    return tag;
  }

  // 如果它是一个函数,其源代码以 "class" 关键字开头
  if (
    baseType === "function" &&
    Function.prototype.toString.call(value).startsWith("class")
  ) {
    return "class";
  }

  // 构造函数的名称;例如 `Array`、`GeneratorFunction`、`Number`、`String`、`Boolean` 或 `MyCustomClass`
  const className = value.constructor.name;
  if (typeof className === "string" && className !== "") {
    return className;
  }

  // 在这一点上,没有合适的方法来获取值的类型,因此我们使用基本实现。
  return baseType;
}

要检查可能不存在的变量,否则会抛出 ReferenceError,请使用 typeof nonExistentVar === 'undefined',因为自定义代码无法模仿这种行为。

规范

Specification
ECMAScript Language Specification
# sec-typeof-operator

浏览器兼容性

BCD tables only load in the browser

参见