JavaScript中值类型与引用类型的区别
1、数据类型分类
-
值类型
值类型又称简单数据类型或基本数据类型,在存储的时候变量中直接存储的是值本身。值类型包括:String、Number、boolean、null
-
引用类型
引用数据类型又称复杂数据类型,在存储的时候变量中存储的仅仅是数据空间的地址,即引用地址,或者说指针。使用new关键字构造出来的对象都是引用类型,比如Object、Array、Date、自定义对象……等。
2、两者之间的区别
-
值类型
占用空间固定,保存在栈中。当一个方法执行时,每个方法都会建立自身的内存栈,在当前方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法内的内存栈也将自动销毁。因此,所有在方法中定义的变量都是放在栈内存中的。栈中存储的是基本变量,以及一些对象的引用变量。基础变量的值是存储在栈中,而引用变量存储在栈中的是指向堆中的数组或者对象的地址,这就是为何修改引用类型,总会影响到其指向这个地址的引用变量。
使用 typeof()方法可以检测数据类型是否只值类型
-
引用类型
占用空间不固定,保存在堆中。当我们在程序中创建一个对象时,这个对象将会保存到运行时数据区中,以便反复利用(因为创建对象的成本相对较大),这个运行时数据区就是堆内存。堆内存中的对象不会随方法的结束而销毁,即便方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时常见),则这个对象依然不会销毁,只要当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在合适的时机将其回收。
使用instanceof可以检测数据类型是否是引用类型
3、栈和堆
- 栈:由操作系统自动分配释放,存放在函数里的参数值、局部变量等数据,值类型数据最终保存在栈里面。直接存储其数据值,调用速度快,但存储数据量小。
- 堆:由程序员进行分配释放,如果程序员不释放,则会由系统的垃圾回收机制自动释放,引用类型数据最终保存在堆里面,但是引用类型的名称存储的是这个堆里面的一个地址。直接用栈存储其数据的引用地址,数据存储在堆中,调用速度慢,但存储数据量大。
4、函数传参
-
值类型传参
在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数,或者用ECMAScript 的概念来说,就是 arguments 对象中的一个元素),简单点说是对值的复制。
-
引用类型
在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部。
5、总结
不管是值类型对函数传参还是引用类型对函数传参都是对数据的复制。只不过不同的是值类型复制的是数据,而引用类型复制的是引用地址。