felix-cao / Blog

A little progress a day makes you a big success!
31 stars 4 forks source link

JavaScript 引用类型(Reference Values) #41

Open felix-cao opened 6 years ago

felix-cao commented 6 years ago

上一篇 《JavaScript 基本数据类型(Primitive Values) 》 聊到了JavaScript的7种基本类型,那么除此之外就是引用类型了,也可以说是对象了。

对象是属性和方法的集合。也就是说引用类型可以拥有属性和方法,属性又可以包含基本类型和引用类型,如Object, Array, Function等。下面来看看引用类型的一些特性。

一、值是可以改变的

var person = { age: 32 };
person.age = 30; // 通过修改对象属性值更改对象
person.name = 'Felix'; // 再次更改对象,给它增加一个属性

var arr = [1, 2, 3];
a[0] = 0; // 更改数组的一个元素
a[3] = 4; // 给数组增加一个元素

二、可以动态添加属性和方法

var person = {};
person.name = 'Felix Cao';
person.getName = function() {
  console.log('Felix Cao');
}

三、赋址

var a = {};
var b = a;
a.name = 'Felix Cao';
console.log(a.name); // Felix Cao
console.log(b.name); // Felix Cao

b.age = 30;
console.log(a.age); // 30
console.log(b.age); // 30

当从一个变量向另一个变量赋值引用类型的值的过程实际上是一个赋的过程,同样也会将储存在变量中的对象的值复制一份放到为新变量分配的空间中.引用类型保存在变量中的是堆区内存地址,该地址存放的是个对象,

所以,与基本数据类型的简单赋值不同,这个值的副本实际上是一个指针,而这个指针指向存储在堆内存的一个对象.那么赋值操作后,两个变量都保存了同一个对象地址,而这两个地址指向了同一个对象.因此,改变其中任何一个变量,都会互相影响, 它们的关系如下图:

因此,引用类型的赋值本质上是对象保存在堆区地址指针的赋值,所以两个变量指向同一个对象,任何的操作都会互相影响。

四、引用类型的比较是内存地址的比较

var a = {};
var b = a;
var person1 = {};
var person2 = {};
console.log('a == b: ', a == b); // true
console.log('person1 == person2: ', person1 == person2); // false

为什么person1person2两个对象看起来一摸一样,但是却不相等呢?

因为引用类型的比较是引用的比较,换句话说,就是比较两个对象保存在栈区的指向堆内存的地址是否相同,此时,虽然person1person2看起来都是一个{},但是他们保存在栈区中的指向堆内存的地址却是不同的,所以两个对象不相等

五、引用类型是同时保存在栈区和堆区中的

引用类型的存储需要在内存的栈区(Stack)和堆区(Heap)共同完成,栈区保存变量标识符和指向堆内存的地址。 假如有以下几个对象:

var person1 = {name:"change1"};
var person2 = {name:"change2"};
var person3 = {name:"change3"};

则这三个对象在内存中保存的情况如下图:

instanceOf

  判断是否是某个对象的类型, 回头单独拿一篇来聊聊indtanceOf.

总结

基本类型和引用类型的区别