原文: JavaScript Type Checking – How to Check Type in JS with typeof()

JavaScript 是一种动态类型(或松散类型)的编程语言。它允许你声明变量而不指定或定义变量类型。

你可以在 JavaScript 中创建一个变量,而不定义你可以存储在该变量中的值的类型。这可能会影响你的程序,并在运行时造成错误,因为类型可以改变。

例如,一个变量可以被声明并分配一个数字。但随着你写的代码越来越多,各个值可能会被放错位置,你可能会给同一个变量分配一个字符串或布尔值。这将在你的代码运行时造成影响:

let myVariable = 45; // => number
myVariable = 'John Doe'; // => string
myVariable = false; // => boolean

从上面的例子可以看出,JavaScript 中的变量可以在程序的整个执行过程中改变类型。作为一个程序员,这可能是很难掌握的。这就是为什么 TypeScript 被认为是 JavaScript 的超集的原因之一。

为了在 JavaScript 中通过检查变量的类型来验证变量,你可以使用 typeof 操作符。在 JavaScript 中,对于非基本数据类型和特定的值,类型检查是不直接的。这就是为什么类型检查会变得很烦人,特别是对于没有经验的 JS 开发者来说。

在这篇文章中,你将学习如何使用 typeof 操作符,在什么情况下你不应该使用 typeof,以及在 JavaScript 中对这种情况进行类型检查的最佳方法。

JavaScript 数据类型

在 JavaScript 中,数据类型被分为两组:基本数据类型和非基本数据类型。除了对象是一个非基本数据类型外,其他都是基本数据类型。

这些数据类型包括:

  • String 字符串
  • Number 数值
  • Boolean 布尔值(true and false 真和假)
  • null
  • undefined
  • Symbol

你可能认为我省略了数组和函数。不是的,这是因为它们都是对象。

如何在 JavaScript 中用 typeof 运算符检查类型

typeof 运算符接受一个操作数(一个单数运算符),并确定操作数的类型。

有两种方法可以使用 typeof 运算符。你可以评估一个单一的值或一个表达式:

typeof(expression);

// 或者

typeof value;

typeof 操作符将返回类型为一个字符串,即 “number”、“string”、"boolean” 等等。

let myVariable = 45;
console.log(typeof myVariable); // 返回 "number"
console.log(typeof(myVariable)); // 返回 "number"

console.log(typeof 45); // 返回 "number"
console.log(typeof(45)); // 返回 "number"

重要的是要知道,在评估一个表达式而不是一个单一的值时,你应该总是使用表达式方法(以函数的形式),比如说:

console.log(typeof(typeof 45)); // 返回 "string"

上面返回的是一个字符串,因为 typeof 45 的输出为 “number”(它被返回为字符串),然后 typeof("number") 的输出为 “string”。

另一个例子是,如果你的数字里有一个连字符:

// 使用表达式
console.log(typeof(123-4567-890)); // 返回 "number"

// 使用一个值
console.log(typeof 123-4567-890); // 返回 NaN

一个值的方法将返回 NaN(不是一个数字),因为它首先会评估 typeof 123,这将返回一个字符串,“number”。这意味着你现在只剩下 "number" - 4567-890,它不能被减去,将返回 NaN

如何检查数值数据类型

现在让我们来探讨一下将返回数值数据类型的可能实例。

在 JavaScript 中,数值可能有不同的值,比如正负整数、零、浮点数和无穷大:

console.log(typeof 33); // 返回 "number"
console.log(typeof -23); // 返回 "number"
console.log(typeof 0); // 返回 "number"
console.log(typeof 1.2345); // 返回 "number"
console.log(typeof Infinity); // 返回 "number"

另一点也很重要,像 NaN 这样的值,尽管它意味着 Not-a-Number(不是一个数字),但总是会返回一个 “number” 的类型。此外,数学函数的数据类型也是数字:

console.log(typeof NaN); // 返回 "number"
console.log(typeof Math.LOG2E); // 返回 "number"

最后,当你使用 Number() 构造函数将一个含有数字的字符串显式地类型转换为一个数字,甚至是一个不能类型转换为整数的字符串这样的值,它将总是返回一个数字作为其数据类型:

// 类型转换一个值为数值
console.log(typeof Number(`123`)); // 返回 "number"

// 不能类型转换为整数的值
console.log(typeof Number(`freeCodeCamp`)); // 返回 "number"

最后,当你使用 parseInt()parseFloat() 等方法将字符串转换为数字,并将数字四舍五入时,其数据类型将是 number:

console.log(typeof parseInt(`123`)); // 返回 "number"
console.log(typeof parseFloat(`123.456`)); // 返回 "number"

如何检查字符串数据类型

只有少数情况下会返回 “string”。这些实例是空字符串、一串字符(这也可以是一个数字)和多个单词:

console.log(typeof ''); // 返回 "string"
console.log(typeof 'freeCodeCamp'); // 返回 "string"
console.log(typeof 'freeCodeCamp offers the best free resources'); // 返回 "string"
console.log(typeof '123'); // 返回 "string"

另外,当你对任何值使用 String() 构造函数时:

console.log(typeof String(123)); // 返回 "string"

如何检查布尔值数据类型

当你检查 truefalse 值时,它总是返回布尔值类型。另外,当你检查任何使用 Boolean() 构造函数的数据时:

console.log(typeof true); // 返回 "boolean"
console.log(typeof false); // 返回 "boolean"
console.log(typeof Boolean(0)); // 返回 "boolean"

此外,当你使用双非运算符(!!)时,它的作用与 Boolean() 构造函数一样,将返回 “boolean”。

console.log(typeof !!(0)); // 返回 "boolean"

如何检查 Symbol 数据类型

当你使用 Symbol() 构造函数时,即使没有传递值,也会返回 “symbol” 数据类型。另外,当你传入一个参数或使用 Symbol.iterator 时,它指定了一个对象的默认迭代器。

console.log(typeof Symbol()); // 返回 "symbol"
console.log(typeof Symbol('parameter')); // 返回 "symbol"
console.log(typeof Symbol.iterator); // 返回 "symbol"

如何检查 Undefined 数据类型

当你声明一个变量而没有给它赋一个值时,就表明它是 undefined。当你检查 undefined、没有值的变量(未定义)和未定义的变量时,它们总是会返回 “undefined”。

// 使用 undefined 关键字
console.log(typeof undefined); // 返回 "undefined"

//声明了一个变量,但是未定义(故意不给它赋值)
let a;
console.log(typeof a); // 返回 "undefined"

// 使用 undefined 变量
console.log(typeof v); // 返回 "undefined"

到目前为止,你已经学会了如何检查除 null 以外的所有基本数据类型的类型。这有点复杂,我在《JavaScript 中的空值检查详解》一文中详细介绍过。

但我将在这篇文章中简要地介绍一下如何检查 null,以便你能理解基础知识。

如何检查 Object 数据类型

某些实例将总是返回 “object”,尽管 null 的情况是一个无法修复的历史 bug,而函数有其技术原因。

console.log(typeof null);
console.log(typeof [1, 2, 3, "freeCodeCamp"]);
console.log(typeof { age: 12, name: "John Doe" });
console.log(typeof [1, 2, 3, 4, 5, 6]);

正如你在上面的例子中所看到的,当你使用 typeof 操作时,数组将总是返回 “object”。这可能不是很令人愉快,但从技术上讲,数组是一种特殊的对象类型:

console.log(typeof [1, 2, 3, 'freeCodeCamp']);

在 ES6 中,Array.isArray 方法被引入,这使得你有可能轻松地检测到一个数组:

console.log(Array.isArray([1, 2, 3, "freeCodeCamp"])); // 返回 true
console.log(Array.isArray({ age: 12, name: "John Doe" })); // 返回 false

另外,在引入 ES6 之前,instanceof 操作符被用来检测一个数组:

const isArray = (input) => {
    return input instanceof Array;
};

console.log(isArray([1, 2, 3, 'freeCodeCamp'])); // 返回 true

如何检查 Null 数据类型

当你使用 typeof 操作符检查 null 值时,由于一个无法修复的历史 bug,它返回 “object”。

注意:不要将 null 与 undefined 混淆。如果一个变量有意包含 null 的值,它就被称为 null。相反,当你声明一个变量而没有赋给它一个值时,它就是 undefined

检测 null 的一个非常直接的方法是使用严格比较法:

const isNull = (input) => {
    return input === null;
}

let myVar = null;
console.log(isNull(myVar)); // 返回 true

你可以阅读这篇文章《检查 JavaScript 中的 null 值》,了解更多的选项和详细的解释。

JavaScript 中类型检查的通用解决方案

Tapas Adhikary 之前的一篇文章《如何在 JS 中检查变量或对象的类型》中,他补充并解释了一个通用的解决方案,你可以用它来更准确地检查类型:

const typeCheck = (value) => {
    const return_value = Object.prototype.toString.call(value);
    const type = return_value.substring(
    return_value.indexOf(" ") + 1,
    return_value.indexOf("]")
    );

    return type.toLowerCase();
};

让我们来测试一下:

console.log(typeCheck([])); // 返回 'array'
console.log(typeCheck(new Date())); // 返回 'date'
console.log(typeCheck(new String("freeCodeCamp"))); // 返回 'string'
console.log(typeCheck(new Boolean(true))); // 返回 'boolean'
console.log(typeCheck(null)); // 返回 'null'

总结

在这篇文章中,你已经学会了如何用 typeof 操作符检查 JavaScript 中的类型。

你还了解了一些限制,以及如何使用其他方法来克服这些限制。请记住,对于大多数基本数据类型,你总是可以使用 typeof 操作符。

Have fun coding!