ext如何将值存入变量_变量类型之值类型与引用类型
前言
變量類型在我們?nèi)粘i_發(fā)中經(jīng)常接觸到,但是js中的變量類型與其他強類型語言不同,由于js是弱類型語言,因此他的變量拷貝在我們實際的日常開發(fā)中有很多需要注意的項。而半斤在最近的開發(fā)中遇到了很多匪夷所思的問題,很多都與變量類型中的引用類型有關(guān),所以想寫一篇文章來總結(jié)概括一下。作為筆記,也分享給小伙伴們。
值類型與引用類型
按照慣例,先上代碼。
let a = 2; const b = a; a = 3; console.log("b:", b) // b:2小伙伴想必一定能一眼看出來這個打印的結(jié)果。這是非常符合我們的直觀邏輯的。那么我們來看下下面這段代碼。
const dabai = {age: 23,hobby: "sing",home: {city: "shanghai"} }const dabaiCopy = dabai; dabaiCopy.home.city = "hangzhou"; console.log("dabai:", dabai);大家知道打印的結(jié)果嗎?
對的,一眼看上去是不是很違反常理,這里的dabai的home屬性下的city屬性竟然是hangzhou。我們上一步的操作明明是修改的dabaiCopy的home.city屬性修改為hangzhou。而不是dabai這個對象。別急,我們繼續(xù)往下看。
首先我們需要先了解一下兩種變量類型,值類型與引用類型。小伙伴們可能對這兩種類型感覺有點陌生?但有沒有想過為什么會有這兩種類型會存在呢?來來來,跟隨skr~的腳步,走~你。
javascript中的數(shù)據(jù)類型
大家都知道,js目前是有8種數(shù)據(jù)類型,其中有7種基本類型是Boolean,Null,Undefined,Number,Bigint, String和Symbol.還有一種復(fù)雜類型Object。而其中Boolean,undefined,string,Symbol,number,Bigint類型是值類型,而Object,Array(可以看成一種特殊的對象類型),特殊的引用類型null,和function(不用于存儲數(shù)據(jù))。這些都可以看成為對象類型。他們的變量類型其實都是引用類型。那為什么我們要區(qū)分開來這兩種類型呢?來,我們不妨先思考一個小問題。
假設(shè)我們需要拷貝一個硬盤里的文件到另一個硬盤中,如果拷貝的文件中有一個5kb小文件,還有一個5tb的大文件,那么我們?nèi)绾稳浞菽?#xff1f;那么我們又如何可以盡量的減少拷貝時的空間占用呢?不急,我們下面會揭曉答案。不過在這之前,我們先來聊聊值類型和引用類型。
值類型
我們要了解值類型,首先我們知道值類型的一些特點。
值類型的特點:占用空間固定,并保存在棧中。當(dāng)執(zhí)行一個函數(shù)時,js引擎會開辟一個內(nèi)存棧來存儲這個函數(shù)中所有的變量。所以當(dāng)我們進行拷貝等操作的時候,js引擎會在棧中對相應(yīng)的變量進行復(fù)制,并創(chuàng)建一個新的變量來存儲,這樣兩個變量之間就沒有任何關(guān)聯(lián)。就好像我們把文件從一個硬盤拷貝到另外一個硬盤中,這兩個硬盤中的同名文件沒有任何關(guān)聯(lián)。是兩個獨立的文件。
下圖演示了怎么拷貝值類型的變量時,我們的內(nèi)存棧中的變化。
從上面兩圖中,我們可以看到,當(dāng)我們執(zhí)行const b = a的時候,棧內(nèi)存中開辟了新的內(nèi)存空間來存儲我們的變量b,并將a的值2賦給了b的value。所以我們可以看到a和b已經(jīng)是兩個不同的變量了。他們存儲在不同的內(nèi)存空間中,所以他們之間互不關(guān)聯(lián),更改其中一個變量的值也不會影響另外一個變量的值。
引用類型
在聊引用類型之前,讓我們先回到之前提出的那個問題?如果我們要拷貝一個大文件從一個硬盤到另一個硬盤,我們應(yīng)該怎么去做?你能想到什么高效的方法可以節(jié)省硬盤的存儲空間嗎?
聰明的你一定想到了百度網(wǎng)盤這一類云盤。對的,云盤可以幫助我們解決硬盤中拷貝文件太大,占用硬盤空間太大的問題。把大文件備份在云端的服務(wù)器中,當(dāng)我們需要的時候,只需要一個云盤的分享鏈接就可以從服務(wù)器端進行拉取,得到大文件中的內(nèi)容。這樣就可以解決大文件的占用硬盤空間問題。
好的,理解了上面的小問題后,讓我們來看看什么是引用類型?
引用類型的特點與它的存儲方式有關(guān),js引擎在存儲這類變量的時候,會開辟一個足夠大的內(nèi)存空間,頂部是棧,底部是堆。棧會把新變量逐漸向下存儲,而堆會向上存儲。但不用擔(dān)心會在中間重復(fù),js引擎會預(yù)留并處理好這個空間,如下左圖。
當(dāng)我們執(zhí)行const a = { name: "dabai"}的時候,分配的內(nèi)存空間中的頂部的棧會存儲一個key為a, value為keya的變量。其中keya表示堆中變量的地址,從上面左邊的圖中可以看到,在底部的堆中keya對應(yīng)的value就是我們要存儲的值{name: "dabai"}。而當(dāng)我們進行賦值操作的時候,就是右邊的圖,執(zhí)行const b = a的時候,js引擎會在棧中新開辟一個用來存儲變量b的空間,然后將a的value拷貝到b的value屬性。所以a和b變量存儲的是同一個內(nèi)存地址keya,指向同一個堆地址keya。而keya的value存儲的是{name: "dabai"}。
當(dāng)我們?nèi)バ薷膶ο骯 的值的時候,比如執(zhí)行a.name = "banjin",那么更改的其實是存儲在堆內(nèi)存中的keya對應(yīng)的value:{name: "dabai"} --> {name: "banjin"},而b對象的value(keya)其實是沒有更改的,也對應(yīng)著堆里的keya。所以這時候打印b的值會打印出{name: "banjin"}。如下圖所示過程。
值類型與引用類型的區(qū)別
看到這里,相信小伙伴已經(jīng)大概理解了值類型與引用類型的區(qū)別了,我們來概括一下,值類型是保存在內(nèi)存棧中的一對鍵值對,對其進行拷貝的時候,js引擎會新建一個變量,然后將值完全拷貝過去,新變量和舊變量之間沒有關(guān)聯(lián)。而引用類型則是在棧中保存著key(變量名)和value(堆中變量存儲的地址)。而棧中的value對應(yīng)著堆中的key(地址)兩者是相等的,而堆中保存的value是實際存儲的值。所以當(dāng)我們更改被拷貝(a)的變量的時候,拷貝的變量(b)也會一起被更改。因為兩者指向同一個堆里的值。
如果上面的引用類型難以理解,那么我們可以想象一下云盤。當(dāng)我們使用云盤進行分享的時候,可以將鏈接發(fā)送給別人,也就是保存引用類型時,棧中的value值。這個鏈接對應(yīng)著云盤中的某個資源,比如說某個5tb的大視頻。也就是堆中保存的value。那么所有拿到鏈接的人都可以獲得我在云盤中存儲的5tb大視頻。而如果我將云盤的這個5tb的視頻進行更改,鏈接依然不變,那其他人重新下載的資源就變成了我更換的視頻了。如下圖
那么為什么需要區(qū)分值類型和引用類型呢?
這個問題就需要回到之前提到的關(guān)于云盤的問題,云盤的出現(xiàn)解決了很多問題。但是我們就存儲大文件這一項進行討論,我們只需要擁有一個鏈接就可以通過網(wǎng)絡(luò)下載存在云盤中的大文件,可以實現(xiàn)多個本地電腦在需要的時候可以拷貝云盤上的同一份文件,而不是所有電腦都拷貝一份,這樣會節(jié)省大量的硬盤空間。所以對于大文件我們一般采用云盤備份,這樣可以有效的減少硬盤占用。而小文件直接保存本地就好,方便。
那換而言之,回到變量類型中來,值類型大多是簡單類型,占用的內(nèi)存小,而引用類型則是復(fù)雜對象類型(一個對象類型通常會包含很多個基本類型)。通常會占用很大的內(nèi)存,對這樣的內(nèi)存進行多份拷貝其實是很損耗內(nèi)存空間的,而且高頻率的賦值拷貝會帶來性能問題。所以js引擎對這兩種類型區(qū)分開來。他們的拷貝方式也是區(qū)分開來了。這樣就可以有效的提高性能與大大減低內(nèi)存空間的損耗。
希望各位小伙伴看到這里可以點個贊,多多交流。走 你~。
本篇文章由一文多發(fā)平臺ArtiPub自動發(fā)布總結(jié)
以上是生活随笔為你收集整理的ext如何将值存入变量_变量类型之值类型与引用类型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bee 字符串转int_Beego在vi
- 下一篇: 统计个人已完成的工作量_已注销注册人数统