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}
}

 

感謝你們對此篇文章提出任何建議。

點擊查看此文章的最新版本和所有內容

相關文章
相關標籤/搜索