在JavaScript中,将数据类型分为两种:基础类型和复杂类型 两种类型的区别是:存储位置不同

1、基础类型

基础类型有以下6种:

  • String
  • Number
  • Boolean
  • Undefined
  • BigInt (ES6新增)
  • Null
  • Symbol(ES6新增)
类型typeof返回的值对象包装器
String"string"String
Number"number"Number
Boolean"boolean"Boolean
Undefined"undefined"N/A
Null"object"N/A
BigInt"bigint"BigInt
Symbol"symbol"Symbol

String

JavaScript 字符串是不可变的。这意味着一旦字符串被创建,就不可能修改它。

let str = 'test'
str = str + 'spring' // 先删除再创建

语言规范要求字符串的最大长度为 253 - 1 个元素,这是精确整数的上限。但是,具有此长度的字符串需要 16384TB 的存储空间,这在任何合理的设备内存中都容纳不了,因此实现倾向于降低阈值,从而允许字符串的长度方便地存储在 32 位整数中。

  • 在 V8(Chrome 和 Node 使用)中,最大长度为 229 - 24(~1GB)。在 32 位系统上,最大长度为 228 - 16(~512MB)。
  • 在 Firefox 中,最大长度为 230 - 2(~2GB)。在 Firefox 65 之前,最大长度为 228 - 1(~512MB)。
  • 在 Safari 中,最大长度为 231 - 1(~4GB)。

对于空字符串,length 为 0。

Number

常见的为十进制,还可以设置八进制(0开头)、十六进制(0x开头)

let intNum = 55 // 10进制的55
let num1 = 070 // 8进制的56
let hexNum1 = 0xA //16进制的10

浮点类型

let floatNum1 = 1.1;
let floatNum2 = 0.1;
let floatNum3 = .1; // 有效,但不推荐
let floatNum = 3.125e7; // 等于 31250000

NaN = not a number 是一个特殊的数值

typeof NaN === 'number' // true

Number 类型仅有一个具有多个表现形式的值:0 同时表示为 -0 和 +0(其中 0 是 +0 的别名)。实际上,这两者之间几乎没有区别;例如,+0 === -0 是 true。然而,当你除以 0 的时候,你要注意到这一点:

console.log(42 / +0); // Infinity
console.log(42 / -0); // -Infinity

Number 类型是一种基于 IEEE 754 标准的双精度 64 位二进制格式的值。它能够存储 2-1074(Number.MIN_VALUE)和 21024(Number.MAX_VALUE)之间的正浮点数,以及 -2-1074 和 -21024 之间的负浮点数,但是它仅能安全地存储在 -(253 − 1)(Number.MIN_SAFE_INTEGER)到 253 − 1(Number.MAX_SAFE_INTEGER)范围内的整数。超出这个范围,JavaScript 将不能安全地表示整数;相反,它们将由双精度浮点近似表示。你可以使用 Number.isSafeInteger() 检查一个数是否在安全的整数范围内。 ±(2-1074 到 21024) 范围之外的值会自动转换:

+Infinity 和 -Infinity 行为类似于数学上的无穷大,但是有一些细微的区别;更多细节,参见 Number.POSITIVE_INFINITYNumber.NEGATIVE_INFINITY

Boolean

[Boolean](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Boolean)类型表示一个逻辑实体并且包括两个值:truefalse

Undefined

Undefined 类型只有一个值:[undefined](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/undefined)Undefined 表示已经定义但未赋值。

Null

Null 类型只有一个值:[null](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/null)Null 代表一个空指针在栈内存中找不到其值地址指向。 值 null 是一个字面量,不像[undefined](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/undefined),它不是全局对象的一个属性。null 是表示缺少的标识,指示变量未指向任何对象。把 null 作为尚未创建的对象,也许更好理解。在 API 中,null 常在返回类型应是一个对象,但没有关联的值的地方使用。

BigInt

BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。

Symbol

[Symbol](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Symbol)唯一并且不可变的原始值并且可以用来作为对象属性的键(如下)。在某些程序语言当中,Symbol 也被称作“原子类型”(atom)。symbol 的目的是去创建一个唯一属性键,保证不会与其它代码中的键产生冲突。

2、引用类型

引用数据类型:

  • Object
  • Array
  • Function

Object

创建object常用方式为对象字面量表示法,属性名可以是字符串或数值 类数组创建方式

const arrayLike = {
  lenth: 3,
  0: 'a',
  1: 'b',
  2: 'c'
}
console.log(Array.from(arrayLike)) // ['a', 'b', 'c']

console.log(arrayLike instanceof Array); // false
console.log(arrayLike.__proto__.constructor === Array); // false
console.log(arrayLike.toString()); // [object Object]
console.log(arrayLike.valueOf()); // {length: 3, 0: 'a', 1: 'b', 2: 'c'}

let array = [];
console.log(array instanceof Array); // true
console.log(array.__proto__.constructor === Array); // true
console.log(array.toString()); // ''
console.log(array.valueOf()); // []

Array

JavaScript数组是一组有序的数据,但跟其他语言不同的是,数组中每个槽位可以存储任意类型的数据。并且,数组也是动态大小的,会随着数据添加而自动增长

Function

函数实际上是对象,每个函数都是 Function类型的实例,而 Function也有属性和方法,跟其他引用类型一样 函数存在三种常见的表达方式:

  • 函数声明
// 函数声明
function sum (num1, num2) {
    return num1 + num2;
}
  • 函数表达式
let sum = function(num1, num2) {
    return num1 + num2;
};
  • 箭头函数
let sum = (num1, num2) => {
    return num1 + num2;
};

3、存储区别

基本类型

let a = 10;
let b = a; // 赋值操作
b = 20;
console.log(a); // 10值

a的值为一个基本类型,是存储在栈中,将a的值赋给b,虽然两个变量的值相等,但是两个变量保存了两个不同的内存地址 下图演示了基本类型赋值的过程: image.png

引用类型

var obj1 = {}
var obj2 = obj1;
obj2.name = "Xxx";
console.log(obj1.name); // xxx

引用类型数据存放在堆中,每个堆内存对象都有对应的引用地址指向它,引用地址存放在栈中。 obj1是一个引用类型,在赋值操作过程汇总,实际是将堆内存对象在栈内存的引用地址复制了一份给了obj2,实际上他们共同指向了同一个堆内存对象,所以更改obj2会对obj1产生影响 下图演示这个引用类型赋值过程: image.png

总结

  • 栈:原始数据类型(UndefinedNullBooleanNumberStringBigIntSymbol
  • 堆:引用数据类型(ObjectArrayFunction

两种类型的区别在于存储位置的不同:

  • 原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
  • 引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

堆和栈的概念存在于数据结构和操作系统内存中,在数据结构中:

  • 在数据结构中,栈中数据的存取方式为先进后出。
  • 堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。

在操作系统中,内存被分为栈区和堆区:

  • 栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
  • 堆区内存一般由开发着分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收。
浙ICP备2021014928号 2023-PRESENT © Eric