JavaScript的堆栈和基本类型、引用类型
类型
简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。
基本类型:
- 在存储时变量中存储的值就是本身,因此叫做值类型。
- 保存具体数据的值。
- 基本类型的值不可变,动态修改了他们的值实际上返回的是新的值,它的原始值不会被改变。
- 基本类型的比较是值比较,只要他们的值相等就认为他们是相等的。在做比较的使用应使用严格的 === 号,因为 == 号会进行类型转换。
- 基本类型的赋值是是在内存中开辟一段栈内存,然后然后再将值赋值到新的栈内存中。基本类型的变量赋值,变量之间相互独立不受影响。
- 值类型的数据有 string 、number、boolean、undefined、null
引用类型:
- 保存数据的值的指针。
- 引用数据类型在存储变量时存储的仅仅是地址(引用),因此叫做引用数据类型。
- 通过new关键词可以创建对象(系统对象、自定义对象)
- 引用类型的数据存放在堆内存中,变量实际上只是一个存放在栈内存中的指针,这个指针指向堆内存中的地址。
- 引用类型的值是可变的。每次对引用类型的操作是其实是操作其对象的引用(保存在栈内存中的指针)。
- 引用类型的比较是引用的比较。
- 引用类型的赋值是传址,共享同一份内存空间,两个变量指向同一对象,两个变量之间的操作会互相影响。(如果想让新变量的操作不影响就变量可以使用一些函数方法生成新的对象,例如:数组可以使用 concat、slice ,对象可以使用 Object.assign 等方法)
- 引用类型有 Object、Array、Date 等
堆和栈
堆栈空间分配:
栈:
- 由操作系统自动分配释放的参数值、局部变量的值等。其操作方式类似于数据结构中的栈。简单数据类型存放在栈内存中。
堆:
- 存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂类型的数据存放在堆内存中。
注意:JavaScript本身没有堆栈的概念,所谓堆栈只是通过其他语言来更好的来理解JavaScript的存储机制。
var a = 10
function fn(x){
x++
console.log('打印x', x)
}
fn(a)
console.log('打印a', a)
// 打印 x= 11
// 打印 a= 10
// 由于a是值类型,在内存中使用的是栈内存。所以在函数中x + 1 只改变了函数内的变量x变量,而a变量未改变。
var obj = { num: 20}
function fn(x){
x.num++
console.log('打印x=', x)
}
fn(obj)
console.log('打印a=', obj)
// 打印x= { num: 21 }
// 打印a= { num: 21 }
// 由于obj是复杂类型使用的是堆内存,在函数fn中的x和外面的obj共享一份存储空间。因此函数中改变了x.num对应存储空间的值,实际也就是改变了obj对应的存储空间的值,因此外面的obj对象的值也会随之改变。
var a = []
var b = []
console.log('打印', a === b)
// 打印 false
var a = {}
var b = {}
console.log('打印', a === b)
// 打印 false
// 引用类型比较的是引用的堆内存地址。变量a和变量b都是表示一个空数组/对象,但是其在内存中的位置不一样,他们指向的不是同一个对象,所以他们做比较是不想等的。