原始值与引用值
在JavaScript中包含两种不同类型的数据:原始值和引用值原始值 :是指不包含任何引用的值(简单值),比如数字、字符串、布尔值、null和undefined。引用值 :是指包含了一个引用的值,比如对象、数组、函数和方法。
1.动态属性
原始值和引用值,都是定义一个变量之后然后我们给它赋值,在赋值这一部分基本差不多,但是在赋值之后,我们可以对这个变量(值)做什么,就会有很大的不同。
首先,对于引用值而言,我们可以对它的属性做什么,比如添加、删除、修改、查看等等。
let person = new Object(); person.name = "海绵宝宝"; console.log(person.name); // 海绵宝宝 复制代码
在这里我们先创建了一个对象(引用值),然后我们将其保存在person这个变量中,随后给该对象添加了一个name属性,并给它赋值海绵宝宝
。最后我们输出这个对象的属性。
但是在原始值中,不能存在属性,我们添加属性之后,会报错。
let name = "海绵宝宝"; name.weighta = 120; console.log(name.weight);//报错(undefined) 复制代码
这里我们本想给name定义一个weight属性,并赋值为120,但是最后我们输出的时候,发现该属性不生效。
注意: 原始值类型的初始化可以只使用原始字面量形式,但是如果使用的new关键字,那么JavaScript就会创建一个object类型的实例。
2.存储方式
引用值和原始值的存储方式也有不同,在我们内存中,有堆和栈两种模式,堆就类似于把一堆数据放在一起,每个数据都有他们的编号;而栈呢,就类似于是排队一般,每一个数据同样也有他们的编号。
在原始值中是,他们的数据都存储在栈中,通过变量名索引找到对应的值。
在引用值中,就会有不同,引用值首先会在栈中存储相应数据的地址,根据地址从而找到在堆中的数据。
这就是原始值和引用值在存储方式上的区别。
3.复制值
原始值与引用值除了在存储方式上不一样,在原始值和引用值通过变量赋值的时候,也会有不同。
原始值:
在原始值通过变量赋值到另一个变量的时候,原始值的数据会被赋值到另一个位置。也就是说,两个变量他们所存储的数据,在栈里面是两个完全不同的位置,他们通过各自的索引找到自己对应的数据。
例如:
let num1 = 10; let num2 = num1; 复制代码
复制之前
num1 | 10 |
复制之后 | |
----------- | ----------- |
num2 | 10 |
num1 | 10 |
我们把上面的表格想象成一个栈就很好理解了。赋值之后的变量指向的并不是之前变量的地址,这也就意味着这两个变量可以独立使用,互不干扰。
引用值:
在引用值的赋值中,例如我们将boj1的值复制给obj2,那么首先,浏览器会将obj1对象数据在堆里面的地址(存储在栈中),复制给obj2,这一点和前面原始值的复制机制是一样的,都是在栈中另外找一个内存空间上来存放obj2用数据位于堆的地址;第二步,通过这个堆的地址,obj1和obj2访问堆里面的数据,但是这里不一样,堆里面的数据没有被之前那样重新找一个地址存放,也就是说,两个变量最后访问到堆里面的数据是同一个地址。
也就是说,其实这两个变量,指向的是同一个对象,只是他们在栈里面存储地址的位置不同而已,但是他们在栈里面存储的数据(也就是对象在堆里面的地址)是一样的。