Vue中的變量賦值問(wèn)題
Vue變量賦值
前些天寫(xiě)Vue項(xiàng)目遇見(jiàn)一個(gè)很有意思問(wèn)題:
將一個(gè)數(shù)據(jù)(類(lèi)型是對(duì)象)賦值給一個(gè)變量,當(dāng)我去改變這個(gè)變量的時(shí)候,給它賦值的數(shù)據(jù)也跟著變化了,當(dāng)我去改變數(shù)據(jù)時(shí),變量也跟著變了,這讓我想起了js中的淺復(fù)制和深復(fù)制,為驗(yàn)證,將對(duì)象(引用類(lèi)型)改成字符竄(基本數(shù)據(jù)類(lèi)型),果然,這個(gè)問(wèn)題就不見(jiàn)了。
在js中有兩種數(shù)據(jù)類(lèi)型
(1) 基本數(shù)據(jù)類(lèi)型:number、string、boolean、null、undefined、symbol(ES6)
(2) 引用數(shù)據(jù)類(lèi)型:object、function(函數(shù)實(shí)際也是對(duì)象)
為何會(huì)分為這兩種數(shù)據(jù)類(lèi)型呢?
個(gè)人見(jiàn)解
在一段程序中必定會(huì)有這樣的場(chǎng)景:
(1) 當(dāng)一個(gè)方法執(zhí)行完后,不再引用的變量會(huì)被銷(xiāo)毀,被引用的變量不會(huì)被銷(xiāo)毀,不會(huì)造成資源浪費(fèi)和多余的性能消耗;
(2) 定義一個(gè)變量時(shí),這個(gè)變量會(huì)被自動(dòng)分到對(duì)應(yīng)內(nèi)存中(棧內(nèi)存和堆內(nèi)存),提高變量查詢(xún)的速度;例如,定義一個(gè)未知大小的變量(如:對(duì)一個(gè)對(duì)象的增加刪除),放在較小內(nèi)存的棧中,棧大小是有默認(rèn)值的,如果申請(qǐng)的臨時(shí)變量太大的話(huà)就會(huì)超過(guò)棧大小,造成棧溢出,很明顯會(huì)影響性能和查找速度。反之,如果一個(gè)固定大小的變量放到堆內(nèi)存中,實(shí)際堆內(nèi)存是可以申請(qǐng)大小的(相當(dāng)于一個(gè)自適應(yīng)的網(wǎng)頁(yè)),只要不超出內(nèi)存大?。缓苊黠@會(huì)造成資源利用不合理。
淺復(fù)制

將一個(gè)對(duì)象的變量賦值給另一個(gè)變量,修改其中一個(gè)變量時(shí),另一個(gè)的值也會(huì)跟著變化,這就是淺復(fù)制,輸出結(jié)果如下:

當(dāng)將對(duì)象修改為字符串時(shí),賦值給一個(gè)變量,修改其中一個(gè)值時(shí),另一個(gè)并不會(huì)變化,如下:

為什么???
原來(lái)在Js中基本數(shù)據(jù)類(lèi)型是直接按值存儲(chǔ)在棧內(nèi)存中的,而引用類(lèi)型的值是存儲(chǔ)在堆內(nèi)存中的,Js代碼都是自上而下的在棧內(nèi)存中執(zhí)行的(有一些資料顯示,js并沒(méi)有從嚴(yán)格意義上去區(qū)分棧和堆,在一些場(chǎng)景下也是有所區(qū)分的,例如:淺復(fù)制和深復(fù)制),那堆內(nèi)存中的數(shù)據(jù)就沒(méi)有用了嗎???
可能是為了解決這個(gè)問(wèn)題,在棧內(nèi)存中給堆內(nèi)存開(kāi)辟一個(gè)專(zhuān)門(mén)用來(lái)放置它的地址,告訴js引擎,我在外面游蕩,但是你可以通過(guò)這個(gè)地址找到我。
所以,這就可以想到,當(dāng)我們直接將一個(gè)引用數(shù)據(jù)類(lèi)型賦值給一個(gè)變量的時(shí)候,實(shí)際上只是在棧內(nèi)存中執(zhí)行復(fù)制了一下這個(gè)對(duì)象的地址,并不是這個(gè)對(duì)象實(shí)際的值,同一個(gè)地址指向的當(dāng)然就是同一個(gè)值。
解決的方法:
既然知道了問(wèn)題所在就要去干掉它,首先定一個(gè)目標(biāo):變量怎樣獲取到對(duì)象實(shí)際的值???
深復(fù)制

通過(guò)上面封裝的方法在執(zhí)行,如下:

問(wèn)題解決了,實(shí)際上這是因?yàn)閛bj通過(guò)遍歷將值都賦值給了變量obj1,obj1也是一個(gè)完整實(shí)體存在了,只是與obj相似而已,當(dāng)然obj1在棧內(nèi)存中也有了一個(gè)自己專(zhuān)屬的地址,所以obj和obj1實(shí)際就不存在任何關(guān)聯(lián)了。
深復(fù)制的方法有很多,介紹一種最常用的:
JSON.parse(JSON.stringify(obj))
個(gè)人理解:
這個(gè)實(shí)際就是利用JSON.stringify(obj)將對(duì)象的內(nèi)容轉(zhuǎn)換成字符串,那么在棧內(nèi)存中就會(huì)給他一個(gè)空間存儲(chǔ),之后這個(gè)字符串想去外面的世界看看有多精彩,通過(guò)JSON.parse還原回原來(lái)的對(duì)象,帶著家一起出走到了堆內(nèi)存中,在棧內(nèi)存中留下了聯(lián)系方式(地址),從而實(shí)現(xiàn)了深復(fù)制。
注意:
JSON.parse(JSON.stringify(obj))不能復(fù)制函數(shù)類(lèi)型,obj也是要可以枚舉才行,在IE7以下瀏覽器會(huì)報(bào)錯(cuò)
對(duì)于js基本數(shù)據(jù)類(lèi)型的賦值談不上是深復(fù)制,因?yàn)槊棵柯暶饕粋€(gè)變量時(shí),棧內(nèi)存中就會(huì)給其一個(gè)固定空間,如下面的a和b,實(shí)際他們兩個(gè)都在各自的空間,空間里面都放著實(shí)際值,互不干擾。
Var a=1; Var b=a;
番外
Null的數(shù)據(jù)類(lèi)型實(shí)際是object類(lèi)型,為何會(huì)在基本數(shù)據(jù)類(lèi)型里面呢???
查看資料很多都說(shuō)是一個(gè)將錯(cuò)就錯(cuò)的bug
實(shí)際想一下,很多關(guān)于提高性能的書(shū)里面都有提到一個(gè)“對(duì)象不用時(shí)就obj=null“,這是因?yàn)闉g覽器有一個(gè)垃圾回收機(jī)制,當(dāng)檢測(cè)到這原有的堆內(nèi)存沒(méi)有被占用了就會(huì)被銷(xiāo)毀,null就相當(dāng)于一個(gè)對(duì)象的空地址,值就是固定的,占用空間是固定的,這可能就是將錯(cuò)就錯(cuò)的原因,沒(méi)有用的全局對(duì)象不手動(dòng)銷(xiāo)毀,瀏覽器在不能檢測(cè)這個(gè)變量何時(shí)不再使用,就不會(huì)銷(xiāo)毀,會(huì)造成內(nèi)存泄漏。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue使用動(dòng)畫(huà)實(shí)現(xiàn)滾動(dòng)表格效果
這篇文章主要為大家詳細(xì)介紹了vue使用動(dòng)畫(huà)實(shí)現(xiàn)滾動(dòng)表格效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
在Vue中延遲執(zhí)行某個(gè)函數(shù)的實(shí)現(xiàn)方式
在Vue中延遲執(zhí)行某個(gè)函數(shù),你可以使用setTimeout()函數(shù)或者Vue提供的生命周期鉤子函數(shù),本文通過(guò)一些示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-12-12
Vue2.0仿餓了么webapp單頁(yè)面應(yīng)用詳細(xì)步驟
本篇文章給大家分享了Vue2.0仿餓了么webapp單頁(yè)面應(yīng)用詳細(xì)步驟,有興趣的朋友可以跟著操作下。2018-07-07
Vue tagsview實(shí)現(xiàn)多頁(yè)簽導(dǎo)航功能流程詳解
基本上后臺(tái)管理系統(tǒng)都需要有多頁(yè)簽的功能,但是因?yàn)橐恍┠_手架項(xiàng)目基本都把這個(gè)功能給集成好了,導(dǎo)致在學(xué)習(xí)或者修改的時(shí)候不知道該如何下手。今天這篇文章就來(lái)聊一聊,vue-element-admin項(xiàng)目是如何實(shí)現(xiàn)多頁(yè)簽功能的2022-09-09
vue時(shí)間戳和時(shí)間的相互轉(zhuǎn)換方式
本文通過(guò)示例代碼介紹了vue時(shí)間戳和時(shí)間的相互轉(zhuǎn)換方式,通過(guò)場(chǎng)景分析介紹了vue3使用組合式api將時(shí)間戳格式轉(zhuǎn)換成時(shí)間格式(2023年09月28日 10:00),感興趣的朋友一起看看吧2023-12-12
vue 使用Jade模板寫(xiě)html,stylus寫(xiě)css的方法
這篇文章主要介紹了vue 使用Jade模板寫(xiě)html,stylus寫(xiě)css的方法,文中還給大家提到了使用jade注意事項(xiàng),需要的朋友可以參考下2018-02-02
vue給input file綁定函數(shù)獲取當(dāng)前上傳的對(duì)象完美實(shí)現(xiàn)方法
這篇文章主要介紹了vue給input file綁定函數(shù)獲取當(dāng)前上傳的對(duì)象完美實(shí)現(xiàn)方法,需要的朋友可以參考下2017-12-12

