跟绝大多数的程序语言类似,JavaScript 有其内置的数据类型。其中又有分 基本数据类型 (primitive values) 以及 对象 (objects)。你知道在 JavaScript 当中有哪些是基本数据类型?哪些是对象?又可以通过什么样的方法来辨别某个变量是什么类型呢?让我们一起来看看吧。
JavaScript 的基本数据类型
截至目前,JavaScript 的数据类型中,有 七个基本数据类型。这七个基本数据类型以外的,全都是属于对象。
基本数据类型是不可变的 (immutable),意思是我们不能改变那个值本身。举例来说字符串 (string) 是其中一个 JavaScript 基本数据类型,我们不能去改变 'Hi' 这一个字符串 (但在其他程序语言,字符串有可能是可变的,例如在 C 就是可变的)。我们仅可以把某个变量,赋予另一个字符串,例如:
let greeting = "Hi";
greeting = "Hello"; // 赋予另一个值,但上面的 'Hi' 本身没变动
JavaScript 的类型中的七个基本数据类型包含
String (字符串)
字符串是最常见的基本数据类型之一。如前面提到,在 JavaScript 当中字符串本身是不可变的。当我们用 substring() 来截取字符串,或用 concat() 来把两个字符串合为一,这些都是会返回一个新的字符串,而非改变原本的字符串。
Boolean (布尔值)
有 true 与 false 两个值的布尔值,也是 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 一样可以用 +, *, -, **, 与 % 等运算符,不过要注意不可以拿 BigInt 跟 number 类型的值交互使用,这会出现 TypeError 。
Undefined
undefined 是一个类型,它本身也是一个值。假如某个变量还没被声明,我们就先使用,在 JavaScript 会出现索引错误 ReferenceError (如果是用 let 与 const 来声明该变量)。但如果是声明了,但没有赋予某个值,这时因为对 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 val | Result |
|---|---|
| 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]