1、引用数据类型也就是对象数据类型object,比如:object、array、function、data等;
2、引用类型的值可以改变:
let person = {name: 'lisa'} person.name = 'Jane' // 通过修改对象属性值更改对象 console.log(person) // 输出:{name: "Jane"} person.age = 18 // 给对象增加一个属性 console.log(person) // 输出:{name: "Jane", age: 18} let arr = [1, 2, 3, 4, 5] arr[0] = 0 // 更改数组的某一个元素 console.log(arr) // 输出:[0, 2, 3, 4, 5] arr[5] = 6 // 给数组增加一个元素 console.log(arr) // 输出:[0, 2, 3, 4, 5, 6]
3、引用类型可以添加属性和方法:
let person = {}person.name = 'lisa'person.say = function () {alert('hello world')}console.log(person.name) // 输出:lisaconsole.log(person.say) // 输出:function () { alert('hello world') }
4、引用类型的赋值是对象引用
let a = {}let b = aa.name = 'lisa'console.log(a.name) // 输出:lisaconsole.log(b.name) // 输出:lisab.age = 18console.log(a.age) // 输出:18console.log(b.age) // 输出:18
看上面的代码,我们发现当从一个变量向另一个变量赋值引用类型的值时候,同样会将存储在变量中的对象的值复制一份放到位新变量分配的空间中,引用类型保存在变量中的是对象在堆内存中的地址。所以,与基本数据类型的简单赋值不同,这个值的副本实际上是一个指针,而这个指针指向存储在堆内存的一个对象。那么赋值操作后,两个变量都保存了同一个对象的地址,而这两个地址都指向了同一个对象,因此,改变其中任何一个变量,都会互相影响。
关系图如下所示:
所以,引用类型的赋值其实是对象保存在栈区地址指针的赋值,所以两个变量指向同一个对象,任何的操作都会互相影响。
5、引用类型的比较是引用的比较
let man = {}let woman = {}console.log(man === woman) // 输出:false
看上面的例子发现,两个对象一模一样,但是却不相等。因为引用类型的比较是引用的比较,换句话说,就是比较两个对象保存在栈区的指向堆内存的地址是否相等,此时,虽然man和woman看起来都是一个“{}”,但是他们保存在栈区中的指向堆内存的地址却是不同的,所以两个对象不相等。
6、引用类型是同时保存在栈区中和堆区中的,引用类型的存储需要在内存的栈区和堆区中共同完成,栈区保存变量标识符和指向堆内存的地址:
let a = {name: 'aaa'}let b = {name: 'bbb'}let c = {name: 'ccc'}
上面三个对象的内存中保存情况如下图: