js数据类型判断

数据类型

ECMAScript 有七种简单数据类型(也称为原始类型):

  • Undefined
  • Null
  • Boolean
  • Number
  • String
  • Symbol
  • BigInt

Symbol(符号)是 ECMAScript 6 新增的。 BigInt 是第七种原始类型,于 ECMAScript 2020 (ES11) 中正式加入。还有一种复杂数据类型叫 Object(对象)。因为在 ECMAScript 中不能定义自己的数据类型,所有值都可以用上述 8 种数据类型之一来表示。

Undefined 类型

Undefined 类型只有一个值,就是特殊值 undefined。当使用变量声明了变量但没有初始化时,就相当于给变量赋予了 undefined 值。

在对未初始化的变量调用 typeof 时,返回的结果是 "undefined",但对未声明的变量调用它时,返回的结果还是 "undefined"。无论是声明还是未声明,typeof 返回的都是字符串 "undefined"。逻辑上讲这是对的,因为虽然严格来讲这两个变量存在根本性差异,但它们都无法执行实际操作。

一般来说,永远不用显式地给某个变量设置 undefined 值。字面值 undefined 主要用于比较,而且在 ECMA-262 第 3 版之前是不存在的。增加这个特殊值的目的就是为了正式明确空对象指针(null)和未初始化变量的区别。

Null 类型

Null 类型同样只有一个值,即特殊值 null。逻辑上讲,null 值表示一个空对象指针,这也是给 typeof 传一个 null 会返回 "object" 的原因。

任何时候,只要变量要保存对象,而当时又没有那个对象可保存,就要用 null 来填充该变量。这样就可以保持 null 是空对象指针的语义,并进一步将其与 undefined 区分开来。

typeof 操作符

因为 ECMAScript 的类型系统是松散的,所以需要一种手段来确定任意变量的数据类型。typeof 操作符就是为此而生的。对一个值使用 typeof 操作符会返回下列字符串之一:

  • “undefined” 表示值未定义
  • “boolean” 表示值为布尔值
  • “string” 表示值为字符串
  • “number” 表示值为数值
  • “object” 表示值为对象(而不是函数)或 null
  • “function” 表示值为函数
  • “symbol” 表示值为符号
  • “bigint” 表示值为大整数

typeof 操作符最适合用来判断一个变量是否为原始类型。更确切地说,它是判断一个变量是否为字符串、数值、布尔值、大整数、符号或 undefined 的最好方式。

下面是使用 typeof 操作符的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const value1 = 1;
const value2 = "1";
const value3 = true;
const value4 = Symbol();
const value5 = 10n;
const value6 = undefined;
const value7 = null;
const value8 = {};
const value9 = [];
const value10 = function () {};

console.log(typeof value1); // "number"
console.log(typeof value2); // "string"
console.log(typeof value3); // "boolean"
console.log(typeof value4); // "symbol"
console.log(typeof value5); // "bigint"
console.log(typeof value6); // "undefined"
console.log(typeof value7); // "object"
console.log(typeof value8); // "object"
console.log(typeof value9); // "object"
console.log(typeof value10); // "function"

typeof

typeof 在某些情况下返回的结果可能会让人费解,但技术上讲还是正确的。比如,调用 typeof null 返回的是 "object"。这是因为在 JavaScript 初代(1995 年,Netscape Navigator 2),值在内存中以 32 位存储,‌前 3 位作为类型标签‌:对象标签为 000,而 null 被表示为全 0(即 0x00000000),导致类型检查误认其为对象。

严格来讲,函数在 ECMAScript 中被认为是对象,并不代表一种数据类型。可是,函数也有自己特殊的属性。为此,就有必要通过 typeof 操作符来区分函数和其他对象。

instanceof 操作符

typeof 虽然对原始值很有用,但它对引用值的用处不大。我们通常不关心一个值是不是对象,而是想知道它是什么类型的对象。为了解决这个问题,ECMAScript 提供了 instanceof 操作符,语法如下:

1
result = variable instanceof constructor

instanceof 的内部实现机制是:通过判断对象的原型链上是否能找到对象的 prototype,来确定 instanceof 返回值,如果变量是给定引用类型(由其原型链决定)的实例,则 instanceof 操作符返回 true

**使用 instanceof 的问题是假定只有一个全局执行上下文。**如果网页里有多个框架,则可能涉及两个不同的全局执行上下文,因此就会有两个不同版本构造函数。如果要把数组从一个框架传给另一个框架,则这个数组的构造函数将有别于在第二个框架内本地创建的数组。

按照定义,所有引用值都是 Object 的实例,因此通过 instanceof 操作符检测任何引用值和 Object 构造函数都会返回 true。类似地,如果用 instanceof 检测原始值,则始终会返回 false,因为原始值不是对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const value1 = {};
const value2 = [];
const value3 = function () {};
const value4 = null;
const value5 = Symbol("value5");
const pattern = new RegExp(/[^0-9]/);

console.log("instanceof value1:", value1 instanceof Object); // true
console.log("instanceof value2:", value2 instanceof Object); // true
console.log("instanceof value3:", value3 instanceof Object); // true
console.log("instanceof value4:", value4 instanceof Object); // false
console.log("instanceof value5:", value5 instanceof Object); // false
console.log("instanceof pattern:", pattern instanceof Object); // true
console.log("--------------------------");
console.log("instanceof value1:", value1 instanceof Object); // true
console.log("instanceof value2:", value2 instanceof Array); // true
console.log("instanceof value3:", value3 instanceof Function); // true
console.log("instanceof pattern:", pattern instanceof RegExp); // true

instanceof

Object.prototype.toString

Object.prototype.toString() 返回 "[object Type]",这里的 Type 是对象的类型。如果对象有 Symbol.toStringTag 属性,其值是一个字符串,则它的值将被用作 Type。许多内置的对象,包括 MapSymbol,都有 Symbol.toStringTag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const toString = Object.prototype.toString;

console.log(toString.call(1)); // [object Number]
console.log(toString.call("1")); // [object String]
console.log(toString.call(true)); // [object Boolean]
console.log(toString.call(undefined)); // [object Undefined]
console.log(toString.call(null)); // [object Null]
console.log(toString.call(Symbol())); // [object Symbol]
console.log(toString.call(2n)); // [object BigInt]
console.log(toString.call({})); // [object Object]
console.log(toString.call([])); // [object Array]
console.log(toString.call(() => {})); // [object Function]
console.log(toString.call(new RegExp(/[^0-9]/))); // [object RegExp]
console.log(toString.call(new Date())); // [object Date]
console.log(toString.call(new Map())); // [object Map]
console.log(toString.call(new Set())); // [object Set]
console.log(toString.call(new WeakMap())); // [object WeakMap]
console.log(toString.call(new WeakSet())); // [object WeakSet]
console.log(toString.call(new Error())); // [object Error]
console.log(toString.call(new Promise(() => {}))); // [object Promise]

toString

以这种方式使用 toString() 是不可靠的;对象可以通过定义 Symbol.toStringTag 属性来更改 Object.prototype.toString() 的行为,从而导致意想不到的结果。例如:

1
2
3
4
5
6
7
8
9
10
const toString = Object.prototype.toString;

const myDate = new Date();
console.log(toString.call(myDate)); // [object Date]

myDate[Symbol.toStringTag] = "myDate";
console.log(toString.call(myDate)); // [object myDate]

Date.prototype[Symbol.toStringTag] = "prototype polluted";
console.log(toString.call(new Date())); // [object prototype polluted]

toStringTag


js数据类型判断
https://www.my-web.cn/js/data-types/
发布于
2026年5月25日
许可协议