anjia / blog

博客,积累与沉淀
106 stars 4 forks source link

数据类型 | JavaScript 原始值 #83

Open anjia opened 2 years ago

anjia commented 2 years ago

关于 JavaScript 的数据类型,准备写个系列文章,思路大约是:数据类型→原始值→基本数据类型→对象→类型转换。

作为系列的第一篇,本文将介绍数据类型、原始数据类型、JavaScript 原始值。内容偏理论,但绝对有用,它能为后续的知识提供一个相对科学的理解思路,以便我们有条理有重点地学习。

数据类型

在计算机科学和计算机编程中,数据类型(或类型)是数据的一个属性,它告诉编译器或解释器程序员打算如何使用数据。数据类型限制了表达式(比如变量/函数)可能采用的值。大多数编程语言都支持整数、浮点数、字符和布尔值等基本数据类型。

程序员→数据类型→编译器/解释器

数据类型是在类型系统中使用的。类型系统的主要目的是减少程序出错的可能性,它将类型和每个计算值相关联,通过检查这些值的流向来确保或证明不会发生类型错误。检查可以是静态的(在编译时),也可以是动态的(在运行时),也可以是两者的结合。类型系统还有其它用途,比如启用编译器的某些优化。

类型系统提供了定义、实现和使用数据类型的各种方法,它通常被指定为编程语言的一部分,并内置在解释器和编译器中。不同的类型系统提供不同程度的类型安全,类型安全是编程语言阻止或防止类型错误的程度。强类型和弱类型(也称松散类型)就是编程语言用来指代类型安全的一个方面,弱类型语言可能会执行隐式类型转换也可能产生不可预测的结果。

strongly typed
weakly typed / loosely typed

几乎所有的编程语言都有明确的数据类型概念,尽管不同的语言可能会使用不同的术语。常见的数据类型有整数、浮点数、字符、字符串、布尔值。

Integer, Floating-point number, Character, String, Boolean

在学习数据类型的时候,需要了解类型的含义、该类型值的存储方式以及能执行的操作,即它是如何定义、实现和使用的。

在 JavaScript 里,有两种数据类型:原始值和对象。在介绍原始值之前,先来了解下原始数据类型。

原始数据类型

primitive data type 原始数据类型

原始数据类型可以是基本类型(作为基本构建块),也可以是内置类型(提供内置支持)。在大多数编程语言中,基本类型都是内置的。大多数语言也支持从基本类型递归构造更复杂的复合类型,许多语言还会提供一组复合数据类型。

基于不同的语言及其实现,原始数据类型可能和计算机内存中的对象是一一对应的,也可能不对应。通常我们都预期在基本原始类型上的操作是最快的,比如整数加法可以作为单个机器指令来执行,有些处理器提供特定的单指令来处理字符序列。基本原始类型几乎总是值类型。

值类型和引用类型,是编程里的两种数据类型。做此区分的语言通常都会提供装箱和拆箱机制。

大多数语言都不允许程序有修改原始数据类型的行为和功能,无论是基本原始类型还是内置原始类型。

原始数据类型具体有哪些,取决于具体的编程语言。比如在 C# 中字符串是一种复合但内置的数据类型,而在 JavaScript 中字符串被同化为基本的和内置的原始数据类型。

JavaScript 原始值

primitive data type 原始数据类型
primitive value 原始值
primitive 原语

在 JavaScript 中,原始值(也称原始数据类型/原语)是指不是对象也没有方法的数据。有7个,分别是 Undefined, Null, Boolean, String, Number, BigInt 和 Symbol。

原始数据类型 = 原始类型,后续也会简称“类型” ~ data type
原始值(ECMAScript 规范里出现频次较高)~ data value
原语,大约是原始类型和原始值的统称。具体看上下文
基本数据类型 = 原始类型 + 对象

大多数情况,在语言实现的最底层,原始值都是直接表示的。

所有的原始值都是不可变的,即它们不能被改变。如下:

// 使用字符串方法,不会改变字符串本身
let foo = 'JavaScript';
console.log(foo);    // JavaScript
foo.toUpperCase();  // JAVASCRIPT
console.log(foo)    // JavaScript

切记,不要混淆原始值本身和分配了原始值的变量,因为变量是可以被重新分配新值的,而已经存在的原始值是不能被修改的。如下:

// 给变量重新赋一个“新”值,而不是“突变/变异”值(mutated 生物学术语)
let foo = 'JavaScript';
foo = foo.toUpperCase();
console.log(foo);  // JAVASCRIPT

对象、数组和函数的值之所以能被修改,是因为它们不是原始值,如前所述“原始值是指不是对象也没有方法的数据”。举个例子感受下原始值和对象(在JS中数组和函数都是对象)的不同,如下:

// 使用数组方法,会改变数组本身
let bar = [];
console.log(bar);  // []
bar.push('JavaScript');
console.log(bar);  // ["JavaScript"]

原始值可以被替换,但是不能被直接修改。

Primitive values are immutable.

JavaScript 中的7个原始值,除了 undefined 和 null 之外,其它的都有一个等价的对象包装器,即 Boolean, String, Number, BigInt 和 Symbol,包装器的 valueOf() 方法返回原始值。概览如下:

primitive value primitive type object
undefined Undefined -
null Null -
Boolean Boolean Boolean
String String String
Number Number Number
BigInt BigInt BigInt
Symbol Symbol Symbol

data value, data type
每个值都有一个关联的类型
在动态语言里,值有类型但是变量没有

主要参考