javascript基本类型和引用类型

javascript赋值

赋值就是把某一个值赋给变量。javascript

我凭什么要把值赋给变量?

变量至关于名字。java

拿我举例,若是我没有名字,当别人叫我帮忙的时候,就只能说:git

“那个个头不高、颜值爆表、头发很硬、坐在角落的小哥哥,过来帮我一下呗!”github

而有名字的状况是:web

“小强快来!”面试

可见变量赋值的意义在于便于使唤。翻译

基本类型的赋值

基本类型的赋值,比如在每一个盒子里放东西。3d

直接赋值

例如,指针

var a = '手机'
console.log(a)  // '手机'

至关于,给一个盒子起名为a,并放进去一个字符串‘手机’。code

将变量赋值给变量

例如,

var a = '苹果'
var b = a
a = ''
console.log(a)  // '' 
console.log(b)  // '苹果' 

var b = a时,至关于:

给一个盒子起名为b,并偷看一下盒子a里面放的什么,而后本身里面放一样的东西。

a = ''时,至关于:

盒子a里面原来的东西不要了,改放一个''进去。

可是,这并不会影响盒子b中的值。

由于,在盒子a里面发生变化的时候,盒子b并不关心。

只有将变量a赋值给变量b,即b = a时,

b才会出现偷看行为,进而使自身的值和a的值同样。

可见,赋值就是复制,特色是赋值事后互不影响

比如我把感冒复制给朋友,我吃完药好了,并不能表明他也好了。

引用类型的赋值

引用类型的赋值,看上去是共享,实际仍是复制。

栈和堆

首先,基本类型采用栈存储,一个萝卜一个坑。

前面也说到,基本类型的赋值,就像在每一个盒子里放东西,好比,

我在a盒子里放个香蕉、

我在b盒子里放个手机、

我在c盒子里放个老鼠、

我在d盒子里放个房子...

问题出现了,

以前,咱们在盒子里放一些很傻很天真的东西,基本没问题,

可是,盒子里能够放房子吗?

这时候,咱们进一步认识一下咱们的盒子(栈存储)有什么特色?

  • 盒子按顺序排列
  • 每一个盒子只能存放一件物品
  • 每一个盒子都不是很大

显然,咱们的盒子不足以装下房子。

并且常识告诉你:

房子里却是能不少的盒子,所以房子就是堆存储。

堆存储就像找了一片空地,而后在上面尽情放盒子(请不要想到《个人世界》)。

特色就是存的多、存的乱。

理解堆和栈的区别,也能够参照公交车,

每一个座位,

有序、只能坐一人、大小有限...

比如栈;

其它地方,

能挤下一堆人,很乱...

比如堆。

对象采用的就是堆存储。

什么是引用类型

咱们知道,javascript引用类型包括对象。

先随便来一个对象:

var a = {}  // 堆存储,至关于建了个房子,名为a

再随便来一个数字:

var b = 10  // 栈存储,至关于选了个盒子,名为b

再随便来一下:

b = a
console.log(b)  // {}

太随便就容易出问题:

本来b是一个正经盒子,a是一个正经房子,

执行b = a以后,b变成了{}

根据上面说的基本类型的赋值,这是否是在说

盒子b虽然以前只是一个小盒子、

可是偷看了一眼房子a以后、

本身发奋图强变成像房子a同样大的盒子、

并复制了房子a里面的东西?

不是的。

盒子b并无为了复制房子a里面的东西而变大,

实际上,a其实从头至尾都只是一个盒子、而不是房子,仅管咱们看到是a被赋值了一个堆存储的对象。

为何呢?

由于引用类型只暴露一个地址给咱们,

操做引用类型的数据时(好比赋值),咱们也只是在操做这个地址、引用、指针...爱叫啥叫啥。

这就比如,你送女友戒指,能够直接放到她手里,这是基本类型;

你送女友法拉利,并不是把法拉利直接放到她手里,而是把车钥匙放到她手里,这就是引用类型;

你送女友房子,并不是把房子直接交给她(除非大家是蜗牛),而是把房钥匙交给她,这也是引用类型。

从赋值上来进一步认识引用类型:

直接赋值

开始说过,

变量至关于名字。

另外一个事实是,

咱们只能给盒子起名字,不能给房子起名字,可是咱们能拿到房子的钥匙

这就是为何说,a其实从头至尾都只是一个盒子。

var b = 10至关于取一个盒子叫b,而后里面放啥啥啥,这没有问题;

因为咱们不能给房子起名字,

因此var a = {}确定不是说:取了一个房子叫a,而后里面放啥啥啥。

其实,和var b = 10的解释如出一辙,var a = {}也至关于

取了一个盒子叫a,而后里面放啥啥啥。

只不过是,b盒子里面放很傻很天真的东西,

a盒子里面放很傻很天真的钥匙,这把钥匙对应一个大房子。

引用类型的直接赋值就是把钥匙放到对应盒子里。

为何只给盒子起名字?

代码中,会出现很频繁的变量赋值行为,

为了保证运行速度,这些行为被优先安排在一批有序的盒子中,偷看、复制、再偷看...

能够说,咱们大部分时间在玩盒子。

可想而知,若是换成玩房子的话,要费多大的力气。

可是呢,房子在咱们的程序中也有着不可或缺的做用,

这时候它就暴露出一个能够找到它的钥匙,至关于它的联系方式

而后放进相应的盒子里,并说:

当你须要个人时候,我会在你身边。

正是由于这样,咱们既便于使唤房子,又便于操做房子里的东西。

将变量赋值给变量

var obj = {name: '小强'}
var obj2 = obj
console.log(obj2)   // {name: '小强'}

首先,var obj = {name: '小强'}是引用类型的直接赋值,

至关于找到一个盒子名obj,把{name: '小强'}这个房子的钥匙放进盒子obj里面。

obj2 = obj能够说和基本类型的变量赋值给变量同样,

盒子obj2偷看一眼盒子obj中放的东西,复制一下,本身里面放一样的东西。

喜出望外的是,居然是一把对应某个房间的钥匙!

这时,obj2就和obj同样,都能访问这把钥匙对应的房间了。

因此引用对象的赋值都是操做钥匙

插播广告: {name: '小强'} == {name: '小强'}吗?

答案是否认的。

这至关于在问,这两个房子的钥匙相同吗?

这两个房子只是在装修上极其类似,咱们不能经过将本身的房子布置得和邻居的房子同样、就能获得邻居家的房钥匙,

程序也是如此。

引用类型赋值面试题

例1、

var a = {n: 1}
var b = a
a.x = a = {n: 2}
console.log(a.x)    // undefined
console.log(b.x)    // {n: 2}

逐句翻译吧:

  1. var a = {n: 1}

取一个盒子名a,建一个房子,钥匙放到盒子a里面;

房子里有个盒子n,放着1。

  1. var b = a

取一个盒子名b,盒子b偷看一下盒子a,哇哦,一把钥匙,

盒子b里面也有了这把钥匙,也能去访问这个房间了。

  1. a.x = a = {n: 2}
  • 变量赋值是从右向左的
  • 对象用.赋值的时候,就是操做对象的某个属性,若是没有该属性就添加一个

咱们经过盒子a中的钥匙,来到了这把钥匙对应的房间,

而后,咱们在这个房间取一个盒子名x,并企图在里面放东西。

执行到a.x = a的时候,咱们还觉得:

是把盒子a里面的钥匙,放进咱们所处房间的盒子X里面吗?

差点就是了,可是后面又有=赋值。

根据变量赋值从右向左,

咱们暂时先不在这个房间里的盒子x放东西,而是优先执行a = {n: 2}

这条语句显然是引用类型的直接赋值,

即建了一个是{n: 2}这种样子的房子,而后把钥匙放到盒子a里面。

在栈和堆里面咱们提到过:

每一个盒子只能存放一件物品。

所以,盒子a首先会抛掉以前的钥匙,而后存下这把新的钥匙。

刚才咱们拿着盒子a以前的钥匙,进到对应的房间,企图在房间的盒子x里放东西;

而后,发现后面还有赋值行为,因此优先执行后面的赋值行为。

可是,当时咱们只是暂停,而不是放弃。

换句话说,是不忘初心,善始善终。

当初咱们进的哪一个房子,想在哪一个盒子放东西,

如今咱们就回到哪一个房子,而后给哪一个盒子放东西,

a.x = a能够看出,咱们在盒子x里放的是盒子a的钥匙,

在这个例子中,盒子a中如今的钥匙就是能打开{n: 2}这间房子的钥匙。

虽说,

变量赋值是从右向左的。

可是,代码执行是从左向右的

不管后面发生了多大变化,a.x都是最早执行的,它的做用就是:

经过钥匙来到一个房间,取盒子x,而后等着在里面放东西。

后面的代码,只能影响这个盒子里放什么东西。

因而,时过境迁:

盒子a里,抛弃旧房子钥匙,放进了一把新房子钥匙,等价于

a = {n: 2}

盒子b里,仍是旧房子的钥匙。

同时,由于在盒子a换钥匙以前,咱们经过盒子a拿到旧钥匙来到旧房子,

并将盒子a换钥匙以后的新钥匙,放进了旧房子的盒子x里面,那盒子b等价于

b = {
    n: 1,
    x: {n: 2}
}

也能够将这个例子稍加处理:

var xiaoMing = {moneyBox: 1}
var xiaoQiang = xiaoMing
xiaoMing.keyBox = xiaoMing = {moneyBox: 200}
console.log(xiaoMing.keyBox)    // undefined
console.log(xiaoQiang.keyBox)    // {moneyBox: 200}

再逐句翻译:

  1. var xiaoMing = {moneyBox: 1}

小明有一把房钥匙,这个房子里有个钱柜,里面放着1元钱。

  1. var xiaoQiang = xiaoMing

小强偷偷复制了一把小明的房钥匙,今后他也能够进出小明的房子。

  1. xiaoMing.keyBox = xiaoMing = {moneyBox: 200}

小明在此房子里作了一个钥匙柜,这个钥匙柜能自动生成一把小明口袋里的钥匙(xiaoMing.keyBox = xiaoMing的做用,可能有点超现实),

可是小明想,我口袋里的钥匙如今就是这个房子的钥匙,放在个人钥匙柜里也没什么意义,

不如这样吧,我再买一套房子,把口袋里的钥匙替换成新房子的钥匙,那这个钥匙柜里不就存下新房子的钥匙了吗。

因而,小明果断又买了一套房子,这个房子里也有个钱柜,里面放200元钱。

小明正准备回旧房子呢,忽然想起来,本身口袋里的钥匙已经替换成新房子的钥匙了

如今他只能进新房子,而进不去旧房子了,郁闷...

再说小强,

小强当初复制的是小明旧房子的钥匙,因此小强依然能来到这个旧房子,

进来后发现,多了一个钥匙柜,而且里面放着一把钥匙,

没错,这就是小明新房子的钥匙。

因此如今的局势很明朗了:

小明只有新房子的钥匙,只能进新房子(并且他应该以为旧房子已经没人能进去了)。

而小强有小明旧房子的钥匙,

同时这个房间里还有小明的新房子的钥匙,因此小强也能进小明的新房子。

用代码表示,就至关于

xiaoMing = {moneyBox: 200}
xiaoQiang = {
    moneyBox: 1,
    keyBox: {moneyBox: 200}
}

 

感谢你们对此篇文章提出任何建议。

点击查看此文章的最新版本和所有内容

相关文章
相关标签/搜索