Vue中的變量賦值問題
Vue變量賦值
前些天寫Vue項目遇見一個很有意思問題:
將一個數(shù)據(jù)(類型是對象)賦值給一個變量,當(dāng)我去改變這個變量的時候,給它賦值的數(shù)據(jù)也跟著變化了,當(dāng)我去改變數(shù)據(jù)時,變量也跟著變了,這讓我想起了js中的淺復(fù)制和深復(fù)制,為驗證,將對象(引用類型)改成字符竄(基本數(shù)據(jù)類型),果然,這個問題就不見了。
在js中有兩種數(shù)據(jù)類型
(1) 基本數(shù)據(jù)類型:number、string、boolean、null、undefined、symbol(ES6)
(2) 引用數(shù)據(jù)類型:object、function(函數(shù)實際也是對象)
為何會分為這兩種數(shù)據(jù)類型呢?
個人見解
在一段程序中必定會有這樣的場景:
(1) 當(dāng)一個方法執(zhí)行完后,不再引用的變量會被銷毀,被引用的變量不會被銷毀,不會造成資源浪費和多余的性能消耗;
(2) 定義一個變量時,這個變量會被自動分到對應(yīng)內(nèi)存中(棧內(nèi)存和堆內(nèi)存),提高變量查詢的速度;例如,定義一個未知大小的變量(如:對一個對象的增加刪除),放在較小內(nèi)存的棧中,棧大小是有默認(rèn)值的,如果申請的臨時變量太大的話就會超過棧大小,造成棧溢出,很明顯會影響性能和查找速度。反之,如果一個固定大小的變量放到堆內(nèi)存中,實際堆內(nèi)存是可以申請大小的(相當(dāng)于一個自適應(yīng)的網(wǎng)頁),只要不超出內(nèi)存大小;很明顯會造成資源利用不合理。
淺復(fù)制
將一個對象的變量賦值給另一個變量,修改其中一個變量時,另一個的值也會跟著變化,這就是淺復(fù)制,輸出結(jié)果如下:
當(dāng)將對象修改為字符串時,賦值給一個變量,修改其中一個值時,另一個并不會變化,如下:
為什么???
原來在Js中基本數(shù)據(jù)類型是直接按值存儲在棧內(nèi)存中的,而引用類型的值是存儲在堆內(nèi)存中的,Js代碼都是自上而下的在棧內(nèi)存中執(zhí)行的(有一些資料顯示,js并沒有從嚴(yán)格意義上去區(qū)分棧和堆,在一些場景下也是有所區(qū)分的,例如:淺復(fù)制和深復(fù)制),那堆內(nèi)存中的數(shù)據(jù)就沒有用了嗎???
可能是為了解決這個問題,在棧內(nèi)存中給堆內(nèi)存開辟一個專門用來放置它的地址,告訴js引擎,我在外面游蕩,但是你可以通過這個地址找到我。
所以,這就可以想到,當(dāng)我們直接將一個引用數(shù)據(jù)類型賦值給一個變量的時候,實際上只是在棧內(nèi)存中執(zhí)行復(fù)制了一下這個對象的地址,并不是這個對象實際的值,同一個地址指向的當(dāng)然就是同一個值。
解決的方法:
既然知道了問題所在就要去干掉它,首先定一個目標(biāo):變量怎樣獲取到對象實際的值???
深復(fù)制
通過上面封裝的方法在執(zhí)行,如下:
問題解決了,實際上這是因為obj通過遍歷將值都賦值給了變量obj1,obj1也是一個完整實體存在了,只是與obj相似而已,當(dāng)然obj1在棧內(nèi)存中也有了一個自己專屬的地址,所以obj和obj1實際就不存在任何關(guān)聯(lián)了。
深復(fù)制的方法有很多,介紹一種最常用的:
JSON.parse(JSON.stringify(obj))
個人理解:
這個實際就是利用JSON.stringify(obj)將對象的內(nèi)容轉(zhuǎn)換成字符串,那么在棧內(nèi)存中就會給他一個空間存儲,之后這個字符串想去外面的世界看看有多精彩,通過JSON.parse還原回原來的對象,帶著家一起出走到了堆內(nèi)存中,在棧內(nèi)存中留下了聯(lián)系方式(地址),從而實現(xiàn)了深復(fù)制。
注意:
JSON.parse(JSON.stringify(obj))不能復(fù)制函數(shù)類型,obj也是要可以枚舉才行,在IE7以下瀏覽器會報錯
對于js基本數(shù)據(jù)類型的賦值談不上是深復(fù)制,因為每每聲明一個變量時,棧內(nèi)存中就會給其一個固定空間,如下面的a和b,實際他們兩個都在各自的空間,空間里面都放著實際值,互不干擾。
Var a=1; Var b=a;
番外
Null的數(shù)據(jù)類型實際是object類型,為何會在基本數(shù)據(jù)類型里面呢???
查看資料很多都說是一個將錯就錯的bug
實際想一下,很多關(guān)于提高性能的書里面都有提到一個“對象不用時就obj=null“,這是因為瀏覽器有一個垃圾回收機制,當(dāng)檢測到這原有的堆內(nèi)存沒有被占用了就會被銷毀,null就相當(dāng)于一個對象的空地址,值就是固定的,占用空間是固定的,這可能就是將錯就錯的原因,沒有用的全局對象不手動銷毀,瀏覽器在不能檢測這個變量何時不再使用,就不會銷毀,會造成內(nèi)存泄漏。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
在Vue中延遲執(zhí)行某個函數(shù)的實現(xiàn)方式
在Vue中延遲執(zhí)行某個函數(shù),你可以使用setTimeout()函數(shù)或者Vue提供的生命周期鉤子函數(shù),本文通過一些示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-12-12Vue2.0仿餓了么webapp單頁面應(yīng)用詳細(xì)步驟
本篇文章給大家分享了Vue2.0仿餓了么webapp單頁面應(yīng)用詳細(xì)步驟,有興趣的朋友可以跟著操作下。2018-07-07Vue tagsview實現(xiàn)多頁簽導(dǎo)航功能流程詳解
基本上后臺管理系統(tǒng)都需要有多頁簽的功能,但是因為一些腳手架項目基本都把這個功能給集成好了,導(dǎo)致在學(xué)習(xí)或者修改的時候不知道該如何下手。今天這篇文章就來聊一聊,vue-element-admin項目是如何實現(xiàn)多頁簽功能的2022-09-09vue 使用Jade模板寫html,stylus寫css的方法
這篇文章主要介紹了vue 使用Jade模板寫html,stylus寫css的方法,文中還給大家提到了使用jade注意事項,需要的朋友可以參考下2018-02-02vue給input file綁定函數(shù)獲取當(dāng)前上傳的對象完美實現(xiàn)方法
這篇文章主要介紹了vue給input file綁定函數(shù)獲取當(dāng)前上傳的對象完美實現(xiàn)方法,需要的朋友可以參考下2017-12-12