ECMAScript变量 - 原始值和引用值

这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战markdown

原始值和引用值

ECMAScript变量能够包含两种不一样类型的数据:原始值和引用值。原始值(primitive value)就是最简单的数据,引用值(reference value)则是由多个值构成的对象。post

在把一个值赋给变量时,JavaScript引擎必须肯定这个值是原始值仍是引用值。spa

原始值

Undefined,Null,Boolean,Number,String和Symbol。保存原始值的变量是按值(by value)访问的,由于咱们操做的就是存储在变量中的实际值。3d

引用值

引用值是保存在内存中的对象。与其余语言不一样,JavaScript不容许直接访问内存位置,所以也就不能直接操做对象所在的内存空间。在操做对象时,实际上操做的是该对象的引用(reference)而非实际的对象自己。为此,保存引用值的变量时按引用(by reference)访问的。指针

注意,在不少语言中,字符串是使用对象表示的,所以被认为是引用类型。ECMAScript打破了这个惯例。code

动态属性

原始值和引用值的定义方式很相似,都是建立一个变量,而后给它赋一个值。不过,在变量保存了这个值以后,能够对这个值作什么,则大有不一样。对于引用值而言,能够随时添加,修改和删除其属性和方法。好比,看下面的示例:orm

let person = new Object()
person.name = '何小生'
console.log(person.name)    // "何小生"
复制代码

这里,首先建立了一个对象,并把它保存在变量person中。而后,给这个对象添加了一个名为name的属性,并给这个属性赋值了一个字符串何小生.在此以后,就能够访问这个新属性,直到对象被销毁或属性被显式的删除。对象

原始值不能有属性,尽管尝试给原始值添加属性不会报错,例如:ip

let name = '何小生'
name.age = 26
console.log(name.age)   // undefined
复制代码

在此,代码想给字符串name定义一个age属性,并给该属性赋值26,紧接着在下一行,属性不见了。记住,只有引用值能够动态天价后面可使用的属性。内存

注意,原始类型的初始化能够只使用原始字面量形式。若是使用的是new关键字,则JavaScript会建立一个Object类型的实际,但其行为相似原始值。下面来看看这两种初始化方式的差别:

let name1 = '何小生'
let name2 = new String('小何')
name1.age = 26
name2.age = 27
console.log(name1.age)    // undefined
console.log(name2.age)    // 27
console.log(typeof name1) // string
console.log(typeof name2) // object
复制代码

复制值

除了存储方式不一样,原始值和引用值在经过变量复制时也有所不一样。在经过变量把一个原始值赋值到另外一个变量时,原始值会被复制到新变量的位置。请看下面的例子:

let num1 = 5
const num2 = num1
复制代码

这里,num1包含数值5。当把num2初始化为num1时,num2也会获得数值5。这个值跟存储在num1中的5是彻底独立的,由于它是那个值的副本。

这两个变量能够独立使用,互不干扰。这个过程如图所示:

image.png

在把引用值从一个变量赋给另外一个变量时,存储在变量中的值也会被复制到新变量所在的位置。区别在于,这里复制的值其实是一个指针,它指向存储在堆内存中的对象。操做完成后,两个变量实际上指向同一个对象,所以一个对象上面的变化会在另外一个对象上反应出来,以下面的例子所示:

let obj1 = new Object()
let obj2 = obj1
obj1.name = '何小生'
console.log(obj2.name)   // '何小生'      值已经被复制了
复制代码

在这个例子中,变量obj1保存了一个新对象的实例。而后,这个值被复制到obj2,此时两个变量都指向了同一个对象。在给obj1建立属性name并赋值后,经过obj2也能够访问这个属性,由于它们都指向同一个对象。

如图,展现了变量与堆内存中对象之间的关系

image.png

公众号:小何成长,佛系更文,都是本身曾经踩过的坑或者是学到的东西

有兴趣的小伙伴欢迎关注我哦,我是:何小玍。 你们一块儿进步鸭

相关文章
相关标签/搜索