摘要:地址傳遞引用類型則是地址傳遞,將存放在棧內存中的地址賦值給接收的變量。即對象的淺拷貝會對主對象進行拷貝,但不會復制主對象里面的對象。
相關知識點
1.javascript變量包含兩種不同數據類型的值:基本類型和引用類型。
基本類型值指的是簡單的數據段,包括es6里面新增的一共是有6種,具體如下:number、string、boolean、null、undefined、symbol。
引用類型值指那些可能由多個值構成的對象,只有一種如下:object。
在將一個值賦給變量時,解析器必須確定這個值是基本類型值還是引用類型值。
2.javascript的變量的存儲方式:棧(stack)和堆(heap)。
棧:自動分配內存空間,系統自動釋放,里面存放的是基本類型的值和引用類型的地址
堆:動態分配的內存,大小不定,也不會自動釋放。里面存放引用類型的值。
基本數據類型是按值訪問的,因為可以操作保存在變量中的實際的值。
引用類型的值是保存在內存中的對象。JavaScript 不允許直接訪問內存中的位置,也就是說不能直接操作對象的內存空間。 在操作對象時, 實際上是在操作對象的引用而不是實際的對象。
基本類型與引用類型最大的區別實際就是 傳值與傳址 的區別
值傳遞:基本類型采用的是值傳遞。
地址傳遞:引用類型則是地址傳遞,將存放在棧內存中的地址賦值給接收的變量。
被復制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。即對象的淺拷貝會對“主”對象進行拷貝,但不會復制主對象里面的對象?!崩锩娴膶ο蟆皶谠瓉淼膶ο蠛退母北局g共享。
基本數據類型Number(賦值操作)
let a=1; let b=a; b //1 b=2; b //2 a //1
數組
let arr1 = [1,2,3]; let arr2 = arr1; arr2 //[1,2,3] arr2.push(4); arr2 //[1,2,3,4] arr1 //[1,2,3,4]
首先棧內存arr1會指向堆內存里的數組,棧內存的arr1保存的是數組的引用,也就相當于內存地址,arr2=arr1,會把arr1的引用賦給arr2,所以arr2也有了數組的引用,此時arr1和arr2指向的是同一個數組,因此一個數組的改變會影響另一個數組的值。
對象
let obj1={count:1,name:"grace",age:1}; let obj2 = obj1; obj2 //{count:1,name:"grace",age:1} obj2.count=2; obj1 //{count:2,name:"grace",age:1} obj2 //{count:2,name:"grace",age:1}
綜上所述,如果是基本數據類型,直接進行賦值操作,這樣就相當于在棧內存中重新開辟了一個新的空間把值傳遞過去;如果是引用類型的值傳遞,進行的就是淺拷貝,淺拷貝賦值的只是對象的引用,如上述obj2=obj1,實際上傳遞的只是obj1的內存地址,所以obj2和obj1指向的是同一個內存地址,所以這個內存地址中值的改變對obj1和obj2都有影響。
深拷貝深拷貝不僅將原對象的各個屬性逐個復制出去,而且將原對象各個屬性所包含的對象也依次采用深復制的方法遞歸復制到新對象上,所以對一個對象的修改并不會影響另一個對象。
數組
法一:for循環
let arr1 = [1,2,3]; let arr2 = copyArr(arr1); function copyArr(arr){ let res=[]; for(let i=0,length=arr.length;i法二: slice
用數組自身的方法,slice、concat方法在運行后會返回新的數組
let arr1 = [1,2,3]; let arr2 = arr1.slice(0);法三: concat
let arr1 = [1,2,3]; let arr2 = arr1.concat();法四:擴展運算符
let arr1 = [1,2,3]; let [...arr2] = arr1;法五:Array.from
如果參數是一個真正的數組,Array.from會返回一個一模一樣的新數組
let arr1 = [1,2,3]; let arr2 = Array.from(arr1);對象
法一:for循環
let obj1={count:1,name:"grace",age:1}; let obj2 = copyObj(obj){ let res = {}; for(let key in obj){ res[key]=obj[key]; } return res; }法二:利用JSON
let obj1={count:1,name:"grace",age:1}; let obj2 = JSON.parse(JSON.stringify(obj1));//使用JSON比較簡單,但是JSON的深拷貝方式會忽略函數對象和原型對象(有待考證)
法三:擴展運算符
let obj1={count:1,name:"grace",age:1}; let {...obj2} = obj1;合成版,可以實現數組和對象的深拷貝function deepCopy(obj){ let result = Array.isArray(obj)?[]:{}; if(obj && typeof obj === "object"){ for(let key in obj){ if(obj.hasOwnProperty(key)){ if(obj[key]&&typeof obj[key]==="object"){ result[key]=deepCopy(obj[key]); }else{ result[key]=obj[key]; } } } } return result; }注意:ES6新增了Object.assign() 方法
第一個參數是目標對象,之后還可以跟一個或多個源對象。它會遍歷一個或多個源對象可枚舉的自有鍵并把它們復制到目標對象,最后返回目標對象
assign是使用=操作符來賦值,Object.assign() 只是一級屬性復制,比淺拷貝多深拷貝了一層而已。用的時候,還是要注意這個問題的
作者:優雅1217
來源:CSDN
原文:https://blog.csdn.net/baidu_3...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/102430.html
摘要:而堆內存主要負責像對象這種變量類型的存儲,如下圖引用類型中復制淺拷貝的只是棧內存中的指針,指向同一個堆內存的對象如何實現深拷貝最簡單的方法就是與方法 淺拷貝只會在引用類型中出現 基本數據類型有哪些,number,string,boolean,null,undefined,symbol以及未來ES10新增的BigInt(任意精度整數)七類。 引用數據類型(Object類)有常規名值對的無...
摘要:深拷貝和淺拷貝問題的本質還是不同數據類型的存儲方式差異,尤其是引用數據類型的特殊。 深拷貝和淺拷貝問題的本質還是不同數據類型的存儲方式差異,尤其是引用數據類型的特殊。showImg(https://segmentfault.com/img/bVbb8XH?w=1058&h=409); 現分別對賦值、淺拷貝、深拷貝做深入研究: 1.賦值 原理:直接將對象指針直接賦值給另一個變量 代碼: ...
摘要:相信人很多學習的過程中都踩了深拷貝和淺拷貝的坑,深拷貝和淺拷貝的區別我就不再贅述了,今天我來寫一下我自己實現深拷貝的各種方法。中的深拷貝也是用類似方法實現。 相信人很多學習js的過程中都踩了深拷貝和淺拷貝的坑,深拷貝和淺拷貝的區別我就不再贅述了,今天我來寫一下我自己實現深拷貝的各種方法。 比較簡單的拷貝方式可以借用瀏覽器的Json對象去實現,先把對象轉化為json字符串,在解析回對...
摘要:中的深拷貝與淺拷貝說到深淺拷貝的時候就不得不說一下中的變量類型了基本類型按值存放在棧內存中的簡單數據段可以直接訪問引用類型存放在堆內存中的對象變量保存的是一個指向存放數據位置的指針訪問引用類型的值時首先從棧中獲取到存放該數據位置的指針然后再 JS中的深拷貝與淺拷貝 說到深淺拷貝的時候就不得不說一下JS中的變量類型了: 基本類型: undefined、null、boolean、numb...
摘要:期深拷貝與淺拷貝的區別如何實現一個深拷貝在回答這個問題前,我們先來回顧一下中兩大數據類型基本類型引用類型基本類型基本類型就是值類型存放在棧內存中的簡單數據段,數據大小確定,內存空間大小可以分配引用類型引用類型存放在堆內存中的對象,變量實際保 20190311期 深拷貝與淺拷貝的區別?如何實現一個深拷貝 在回答這個問題前,我們先來回顧一下JS中兩大數據類型 基本類型 Undefined...
閱讀 3175·2021-09-10 10:51
閱讀 3359·2021-08-31 09:38
閱讀 1652·2019-08-30 15:54
閱讀 3138·2019-08-29 17:22
閱讀 3219·2019-08-26 13:53
閱讀 1969·2019-08-26 11:59
閱讀 3290·2019-08-26 11:37
閱讀 3317·2019-08-26 10:47