这是我参与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是彻底独立的,由于它是那个值的副本。
这两个变量能够独立使用,互不干扰。这个过程如图所示:
在把引用值从一个变量赋给另外一个变量时,存储在变量中的值也会被复制到新变量所在的位置。区别在于,这里复制的值其实是一个指针,它指向存储在堆内存中的对象。操做完成后,两个变量实际上指向同一个对象,所以一个对象上面的变化会在另外一个对象上反应出来,以下面的例子所示:
let obj1 = new Object()
let obj2 = obj1
obj1.name = '何小生'
console.log(obj2.name) // '何小生' 值已经被复制了
复制代码
在这个例子中,变量obj1保存了一个新对象的实例。而后,这个值被复制到obj2,此时两个变量都指向了同一个对象。在给obj1建立属性name并赋值后,经过obj2也能够访问这个属性,由于它们都指向同一个对象。
如图,展现了变量与堆内存中对象之间的关系
公众号:
小何成长
,佛系更文,都是本身曾经踩过的坑或者是学到的东西有兴趣的小伙伴欢迎关注我哦,我是:
何小玍。
你们一块儿进步鸭