JavaScript 中的数据类型

80 阅读5分钟

跟绝大多数的程序语言类似,JavaScript 有其内置的数据类型。其中又有分 基本数据类型 (primitive values) 以及 对象 (objects)。你知道在 JavaScript 当中有哪些是基本数据类型?哪些是对象?又可以通过什么样的方法来辨别某个变量是什么类型呢?让我们一起来看看吧。

JavaScript 的基本数据类型

截至目前,JavaScript 的数据类型中,有 七个基本数据类型。这七个基本数据类型以外的,全都是属于对象。

基本数据类型是不可变的 (immutable),意思是我们不能改变那个值本身。举例来说字符串 (string) 是其中一个 JavaScript 基本数据类型,我们不能去改变 'Hi' 这一个字符串 (但在其他程序语言,字符串有可能是可变的,例如在 C 就是可变的)。我们仅可以把某个变量,赋予另一个字符串,例如:

let greeting = "Hi";
greeting = "Hello"; // 赋予另一个值,但上面的 'Hi' 本身没变动

JavaScript 的类型中的七个基本数据类型包含

String (字符串)

字符串是最常见的基本数据类型之一。如前面提到,在 JavaScript 当中字符串本身是不可变的。当我们用 substring() 来截取字符串,或用 concat() 来把两个字符串合为一,这些都是会返回一个新的字符串,而非改变原本的字符串。

Boolean (布尔值)

truefalse 两个值的布尔值,也是 JavaScript 的基本数据类型。

Number

JavaScript 与一些语言不同,没有分整数与浮点数,而是都用 number 这个基本数据类型。不论整数或浮点数,都是 number 这个类型。在 JavaScript 当中, +Infinity-Infinity, 与  NaN 都是 number 这个类型,所以我们用 typeof 来检查的话,会得到 number

console.log(typeof NaN); // number

number 在 JavaScript 是双精度浮点数,所以精确度是介于 -(2^53 − 1)2^53 − 1 之间。在这个范围之外,就会有精准度的问题,这时候要用另一个基本数据类型 BigInt

BigInt

上面提到在 JavaScript 的整数与浮点数,都是用 number 这个类型,这其实只说了一半。因为 JavaScript 的 number 精准度有其限制,虽然多数情况很够用 ( 2^53 - 1 会是 9007199254740991,我们很少用到比这大的数)。但有些时候会需要更往下的精准度。这时就可以用 BigInt 数值的类型。

BigInt 可以让我们任意选择其精准度,就可以避免一些 number 会遇到的问题。它跟 number 一样可以用 +*-**, 与  % 等运算符,不过要注意不可以拿 BigIntnumber 类型的值交互使用,这会出现 TypeError

Undefined

undefined 是一个类型,它本身也是一个值。假如某个变量还没被声明,我们就先使用,在 JavaScript 会出现索引错误 ReferenceError (如果是用 letconst 来声明该变量)。但如果是声明了,但没有赋予某个值,这时因为对 JavaScript 来说,它不知道该变量的值是什么,所以会打打印出 undefined

// 还没声明就使用,会有 `ReferenceError`
console.log(greeting); // Uncaught ReferenceError: greeting is not defined
let greeting;
// 声明了但还没赋值,会是 `undefined`
let greeting;
console.log(greeting); // undefined

Null

null 是很容易跟 undefined 搞混的基本数据类型。 undefined 是因为某变量还没有赋值,所以对 JavaScript 来说,它不知道该变量的值是什么,所以要读取该变量时,会是 undefined。不过 null 则是我们赋予某个变量 null 这一个值。

Symbol

最后一个 JavaScript 基本数据类型是 Symbol,它是一个唯一 (unique) 值,多半会搭配对象一起使用,作为对象的键 (key)。

const sym = Symbol("ExplainThis");
const obj = { [sym]: "Interview Preps for Software Engineers" };
obj[sym]; // Interview Preps for Software Engineers

JavaScript 的对象 (objects)

除了上述的七个基本数据类型以外的存在,在 JavaScript 当中都是对象。在 JavaScript 有一个梗是

Objects, Arrays, Functions, Objects 当中,Objects 好像被重复提了两次。喔不,其实是四次。

会说 Objects 被提了四次说因为在 JavaScript 当中,Array (数组) 与 Function (函数),都是对象。

如何辨别一个变量的数据类型?

要辨别一个变量的数据类型,最常见的方式是通过 typeof 这个方法。举例来说 typeof 判断字符串。

let greeting = "hi";
console.log(typeof greeting); // 'string'

不过在 JavaScript 当中,有几个小例外,其中一个是 null 。如果用 typeof 判断 null 的数据类型,会得到 object

console.log(typeof null); // object

这是一个 JavaScript 的历史遗留问题,但因为要改掉这个 bug 的成本太高,所以到目前为止还是有这个错误。

不论如何, null 的数据类型应该是 null 而不是 object。

另一点要注意的是, typeof 判断数组时,会返回 object; 但判断函数时,会返回 function

console.log(typeof []); // object
console.log(typeof function () {}); // function

补充 typeof 结果的表格,来源参考 ECMAScript® 2015 Language Specification

Type of valResult
Undefined"undefined"
Null"object"
Boolean"boolean"
Number"number"
String"string"
Object (native and does not implement [[Call]])"object"
Object (native or host and does implement [[Call]])"function"
Object (host and does not implement [[Call]])Implementation-defined except may not be "undefined", "boolean", "number", or "string".

我们该如何辨别某个变量是对象,还是数组呢?

Array.isArray() 是可以帮助我们的方法。如果是数组,会返回 true;但若是一般对象,则会返回 false。举例来说:

Array.isArray([1, 2, 3]); // true
Array.isArray({ foo: 123 }); // false

我们也可以通过 Object.prototype.toString() 的方法帮助我们辨别数组、函数与一般对象。

const arr = [1, 2, 3];
const fn = () => {
  return 123;
};
const obj = { foo: 123 };

console.log(Object.prototype.toString.call(arr)); // [object Array]
console.log(Object.prototype.toString.call(fn)); // [object Function]
console.log(Object.prototype.toString.call(obj)); // [object Object]