摘要:內(nèi)存空間分為兩種,棧內(nèi)存與堆內(nèi)存棧是系統(tǒng)自動(dòng)分配的內(nèi)存空間,由系統(tǒng)自動(dòng)釋放,堆則是動(dòng)態(tài)分配的內(nèi)存,大小不定不會(huì)自動(dòng)釋放。
JavaScript的內(nèi)存空間
在JavaScript中,每一個(gè)數(shù)據(jù)都需要一個(gè)內(nèi)存空間。內(nèi)存空間分為兩種,棧內(nèi)存(stack)與堆內(nèi)存(heap)
棧是系統(tǒng)自動(dòng)分配的內(nèi)存空間,由系統(tǒng)自動(dòng)釋放,堆則是動(dòng)態(tài)分配的內(nèi)存,大小不定不會(huì)自動(dòng)釋放。
基本數(shù)據(jù)類型JavaScript中的基本數(shù)據(jù)類型,這些值都有固定的大小,保存在棧內(nèi)存中,由系統(tǒng)自動(dòng)分配存儲(chǔ)空間在棧內(nèi)存空間的值,我們可以直接進(jìn)行操作,因此基礎(chǔ)數(shù)據(jù)類型都是按照值訪問
在棧內(nèi)存中的數(shù)據(jù)發(fā)生復(fù)制的行為時(shí),系統(tǒng)會(huì)自動(dòng)為新變量開辟一個(gè)新的內(nèi)存空間,當(dāng)復(fù)制執(zhí)行后,兩個(gè)內(nèi)存空間的值就互不影響,改變其中一個(gè)不會(huì)影響另一個(gè)
棧內(nèi)存空間數(shù)據(jù)復(fù)制示例 var a = `I am variable a`; var b = a; console.log(b); //`I am variable a` b = `I am variable b`; console.log(a); //`I am variable a` console.log(b); //`I am variable b`引用數(shù)據(jù)類型
引用類型的值是保存在堆內(nèi)存中的對(duì)象,在JavaScript中我們不能直接操作對(duì)象的堆內(nèi)存空間。因?yàn)橐妙愋偷闹刀际前匆迷L問的,所以在操作對(duì)象時(shí),實(shí)際上是操作對(duì)象的引用而不是實(shí)際的對(duì)象。引用可以理解為保存在棧內(nèi)存中的一個(gè)地址,該地址指向堆內(nèi)存中的一個(gè)實(shí)際對(duì)象
引用類型值的復(fù)制,系統(tǒng)會(huì)為新的變量自動(dòng)分配一個(gè)新的棧內(nèi)存空間這個(gè)棧內(nèi)存空間保存著與被復(fù)制變量相同的指針,盡管他們在棧內(nèi)存中的內(nèi)存空間的位置互相獨(dú)立但是在堆內(nèi)存中訪問到的對(duì)象實(shí)際上是同一個(gè),因此,當(dāng)我們改變其中一個(gè)對(duì)象的值時(shí),實(shí)際上就是改變原來的對(duì)象
棧內(nèi)存空間保存指針(地址),堆內(nèi)存空間保存實(shí)際的對(duì)象,我們通過變量訪問對(duì)象時(shí),實(shí)際上訪問的是對(duì)象的引用(地址)
內(nèi)存中的棧區(qū)域存放變量(基本類型的變量包括變量聲明和值)以及指向堆區(qū)域存儲(chǔ)位置的指針(引用類型的變量包括變量聲明和指向內(nèi)容的指針)
var a = { name : `I am object a`, type : "object" } var b = a; console.log(b); // {name: "I am object a", type: "object"} b.name = `I am object b`; console.log(a); // {name: "I am object b", type: "object"} console.log(b); // {name: "I am object b", type: "object"}基本類型總結(jié)
基本數(shù)據(jù)類型:
包括:null、undefined、number、string、boolean、symbol(es6)
存放位置:內(nèi)存中的棧區(qū)域中
比較:值的比較,判斷是否相等,如果值相等,就相等。一般使用===進(jìn)行比較,因?yàn)?=會(huì)進(jìn)行類型的轉(zhuǎn)換
拷貝:賦值(通過(=)賦值操作符 賦值),賦值完成后,兩個(gè)變量之間就沒有任何關(guān)系了,改變其中一個(gè)變量的值對(duì)另一個(gè)沒有任何影響
引用類型總結(jié)引用數(shù)據(jù)類型:
包括:數(shù)組、對(duì)象、函數(shù)
存放位置:內(nèi)存的棧區(qū)域中存放變量和指針,堆區(qū)域存儲(chǔ)實(shí)際的對(duì)象
比較:是引用的比較(就是地址的比較,變量在棧內(nèi)存中對(duì)應(yīng)的指針地址相等就指向同一個(gè)對(duì)象)判斷是否為同一個(gè)對(duì)象,示例如下
變量a和變量b的引用不同,對(duì)象就不是同一個(gè)對(duì)象 var a = {name:"Jay"}; var b = {name:"Jay"}; a===b //false
我們對(duì)JavaScript中引用類型進(jìn)行操作的時(shí)候,都是操作其對(duì)象的引用(保存在棧內(nèi)存中的指針)
賦值、深拷貝和淺拷貝 (Assignment, deep copy and shallow copy)賦值:兩個(gè)變量的值(指針)都指向同一個(gè)對(duì)象,改變其中一個(gè),另一個(gè)也會(huì)受到影響
所謂拷貝就是復(fù)制,通過復(fù)制原對(duì)象生成一個(gè)新的對(duì)象
淺拷貝:重新在堆內(nèi)存中開辟一個(gè)空間,拷貝后新對(duì)象獲得一個(gè)獨(dú)立的基本數(shù)據(jù)類型數(shù)據(jù),和原對(duì)象共用一個(gè)原對(duì)象內(nèi)的引用類型數(shù)據(jù),改變基本類型數(shù)據(jù),兩個(gè)對(duì)象互不影響,改變其中一個(gè)對(duì)象內(nèi)的引用類型數(shù)據(jù),另一個(gè)對(duì)象會(huì)受到影響
var obj = { name: "Jay Chou", age: 32, song:{ name:"發(fā)如雪", year:2007 } } var obj1 = obj; function shallowCopy(obj){ var scObj = {}; for(var prop in obj){ if(obj.hasOwnProperty(prop)){ scObj[prop] = obj[prop] } } return scObj; } var obj2 = shallowCopy(obj); console.log(obj === obj1,"obj === obj1","賦值"); console.log(obj === obj2,"obj === obj2","淺拷貝"); // true "obj === obj1" "賦值" // false "obj === obj2" "淺拷貝" console.log(obj.song === obj2.song); //true obj2.song.name="雙截棍"; obj2.name="Jay"; console.log(obj) // {name: "Jay Chou", age: 32, song: {name:"雙截棍",year:2007}} console.log(obj1); // {name: "Jay Chou", age: 32, song: {name:"雙截棍",year:2007}} console.log(obj2); {name: "Jay", age: 32, song: {name:"雙截棍",year:2007}} console.log(obj===obj1) //true console.log(obj===obj2) //false
深拷貝:不論是對(duì)象內(nèi)的基本類型還是引用類型都被完全拷貝,拷貝后兩個(gè)對(duì)象互不影響
一種比較簡單實(shí)現(xiàn)方法是使用var dcObj = JSON.parse(JSON.stringify(obj))
var obj = { name: "Jay Chou", age: 32, song:{ name:"發(fā)如雪", year:2007 } } var dcObj=JSON.parse(JSON.stringify(obj)); console.log(dcObj); // {name: "Jay Chou", age: 32, song: {name:"發(fā)如雪",year:2007}} console.log(dcObj.song === obj.song); //false dcObj.name="Jay"; dcObj.song.name="雙截棍"; console.log(obj); // {name: "Jay Chou", age: 32, song: {name:"發(fā)如雪",year:2007}} console.log(dcObj); //{name: "Jay", age: 32, song: {name:"雙截棍",year:2007}}
需要注意的是,使用JSON.Stringify()序列化對(duì)象時(shí)會(huì)把對(duì)象內(nèi)的function和原型成員忽略掉,示例如下
var obj = { name: "Jay Chou", job: "artist", say:function(){ alert(this.job); } } JSON.stringify(obj); //"{"name":"Jay Chou","job":"artist"}"
通過遞歸淺拷貝函數(shù)實(shí)現(xiàn)深拷貝
function deepCopy(obj){ if(!obj || typeof obj !== "object"){ return ; } var dcObj = Array.isArray(obj) ? [] : {}; for(var key in obj){ if(obj.hasOwnProperty(key)){ if(obj[key] && typeof obj[key] === "object"){ dcObj[key] = Array.isArray(obj[key]) ? [] : {}; dcObj[key] = deepCopy(obj[key]); } dcObj[key] = obj[key] } } return dcObj; }
比較:賦值、深拷貝、淺拷貝
賦值:變量獲得原對(duì)象的引用,改變該引用指向的對(duì)象的值(基本類型和引用類型)其實(shí)就是修改原對(duì)象的值
淺拷貝:改變新對(duì)象基本類型的值不會(huì)使原對(duì)象對(duì)應(yīng)的值一起改變,但是改變新對(duì)象引用類型的值會(huì)使原對(duì)象對(duì)應(yīng)的值一同改變
深拷貝:改變新對(duì)象基本類型和引用類型的值,都不會(huì)影響原對(duì)象,兩者互相獨(dú)立,互不影響
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/103594.html
摘要:深拷貝和淺拷貝的區(qū)別背景最近在用框架寫頁面,賦值給中的對(duì)象時(shí)會(huì)出現(xiàn)一個(gè)問題,賦值和被賦值對(duì)象之中任何一個(gè)有變化,另一個(gè)也會(huì)隨之變化。 深拷貝和淺拷貝的區(qū)別 背景:最近在用vue框架寫頁面,賦值給Vue.$data中的對(duì)象時(shí)會(huì)出現(xiàn)一個(gè)問題,賦值和被賦值對(duì)象之中任何一個(gè)有變化,另一個(gè)也會(huì)隨之變化。例如: var b = { foo: 123 }; var vm = new Vue(...
摘要:實(shí)際上,是禁止這樣做的。傳值和傳址基本數(shù)據(jù)類型賦值基本數(shù)據(jù)類型的賦值是在內(nèi)存中新開辟一段棧內(nèi)存,然后再把再將值賦值到新的棧中。結(jié)果見輸出,可以看出來,無論是修改賦值得到的對(duì)象和淺拷貝得到的都會(huì)改變原始數(shù)據(jù)。 存儲(chǔ)問題:深拷貝和淺拷貝的主要區(qū)別:在內(nèi)存中的存儲(chǔ)類型(堆和棧)不同堆:動(dòng)態(tài)分配的內(nèi)存,大小不定也不會(huì)自動(dòng)釋放棧:自動(dòng)分配的內(nèi)存,由系統(tǒng)自動(dòng)釋放數(shù)據(jù)類型: 基本數(shù)據(jù)類型: jav...
摘要:深拷貝和淺拷貝問題的本質(zhì)還是不同數(shù)據(jù)類型的存儲(chǔ)方式差異,尤其是引用數(shù)據(jù)類型的特殊。 深拷貝和淺拷貝問題的本質(zhì)還是不同數(shù)據(jù)類型的存儲(chǔ)方式差異,尤其是引用數(shù)據(jù)類型的特殊。showImg(https://segmentfault.com/img/bVbb8XH?w=1058&h=409); 現(xiàn)分別對(duì)賦值、淺拷貝、深拷貝做深入研究: 1.賦值 原理:直接將對(duì)象指針直接賦值給另一個(gè)變量 代碼: ...
摘要:接下來我們進(jìn)入正片數(shù)據(jù)類型六種基本數(shù)據(jù)類型布爾值,和一個(gè)表明值的特殊關(guān)鍵字。一種數(shù)據(jù)類型,它的實(shí)例是唯一且不可改變的。在中是沒有方法是可以改變布爾值和數(shù)字的。參考資料深拷貝淺拷貝 前言 筆者最近整理了一些前端技術(shù)文章,如果有興趣可以參考這里:muwoo blogs。接下來我們進(jìn)入正片: js 數(shù)據(jù)類型 六種 基本數(shù)據(jù)類型: Boolean. 布爾值,true 和 false. nu...
閱讀 1166·2023-04-25 17:28
閱讀 3617·2021-10-14 09:43
閱讀 3978·2021-10-09 10:02
閱讀 1951·2019-08-30 14:04
閱讀 3142·2019-08-30 13:09
閱讀 3280·2019-08-30 12:53
閱讀 2907·2019-08-29 17:11
閱讀 1833·2019-08-29 16:58