摘要:判斷是深拷貝對象還是數(shù)組如果要拷貝的對象的屬性依然是個(gè)復(fù)合類型,遞歸運(yùn)用遞歸,當(dāng)要拷貝的對象或者數(shù)組的屬性依然是個(gè)對象或者數(shù)組時(shí),遞歸調(diào)用。遍歷對象聊完了深拷貝和淺拷貝,接下來說一下遍歷。
在js這門語言中,數(shù)據(jù)存放在堆中,而數(shù)據(jù)的引用的存放在棧中。
淺拷貝我們說的淺拷貝,指的是,引用地址的拷貝,棧中兩塊不同的引用地址都指向了堆中同樣一塊區(qū)域。所以,我們通過一個(gè)地址修改了堆中的數(shù)據(jù),另外一個(gè)引用的地址同樣會(huì)改變。
淺拷貝的常見寫法有直接復(fù)制賦值,使用Object.assign()也是淺拷貝。
let obj = { "a":1, "b":2, "c":{ "c1":3, "c2":4 } } obj.b = 22 let newObj = obj let newObj2 = Object.assign({},obj) console.log(newObj) // newObj.b為22 console.log(newObj2) // newObj.b也為22深拷貝
和淺拷貝不同的是,深拷貝是多帶帶開辟一段堆內(nèi)存空間,把之前堆內(nèi)存中的對象復(fù)制,這樣在棧內(nèi)存的新的引用會(huì)指向新的堆內(nèi)存空間,新老兩塊空間彼此并沒有直接的聯(lián)系,這樣的話,我們修改了之前的對象,新拷貝的對象并不會(huì)隨之改變。
常見的深拷貝方法有兩種,一種是遞歸,另外一種是JSON序列化。
function deepCopy(obj){ let newObj = obj.constructor === Array ? []: {} //判斷是深拷貝對象還是數(shù)組 for(let i in obj){ if(typeof obj[i] === "object") { newObj[i] = deepCopy(obj[i]) // 如果要拷貝的對象的屬性依然是個(gè)復(fù)合類型,遞歸 } else { newObj[i] = obj[i] } } return newObj } let obj = { "a":1, "b":2, "c":{ "c1":3, "c2":4 } } let arr = [1,2,3,[4,5,6],7] let newObj = deepCopy(obj) let newArr = deepCopy(arr) obj.b = 22 arr[3][1] = 55 console.log(obj.b,newObj.b) // 22 2 console.log(arr[3][1],newArr[3][1]) //55 5
運(yùn)用遞歸,當(dāng)要拷貝的對象或者數(shù)組的屬性依然是個(gè)對象或者數(shù)組時(shí),遞歸調(diào)用。
除了遞歸的方式,使用JSON序列化可以很方便的解決深拷貝問題。
// 依然使用上面的例子 let newObj = JSON.parse(JSON.stringify(obj))
這種方法很巧妙很簡單,但是,局限性在于不能拷貝繼承的屬性,原型中的屬性。只有在一些簡單的場合才推薦使用。
遍歷對象聊完了深拷貝和淺拷貝,接下來說一下遍歷。因?yàn)槲覀儼l(fā)現(xiàn),上面深拷貝的時(shí)候執(zhí)行遞歸的時(shí)候,采用的是for ...in的遍歷方式。
除了for...in,在js中的遍歷方式還有很多,比如Object.keys(),for...of等等,那么這些遍歷方式有什么不同呢。
Object.keys()這個(gè)方法用于遍歷,能夠遍歷出來的東西是對象中所有的可枚舉的屬性,但是不包括繼承過來了。
for...infor...in一般用于遍歷對象,能夠返回對象包括繼承過來的可枚舉屬性。
Object.getOwnPropertyNames(obj)返回對象所有的屬性,也包括不可枚舉的屬性。但是不包括繼承過來的。
這個(gè)函數(shù)會(huì)返回一個(gè)數(shù)組。
這三個(gè)遍歷對象的方法,都不會(huì)返回對象中的symbol屬性。
遍歷數(shù)組和遍歷對象不同,遍歷數(shù)組也有一些方法。
for...infor...in除了可以遍歷對象,也可以遍歷數(shù)組,所以上面的例子我們可以用for...in分別遍歷對象和數(shù)組。
forEach()這是ES5新提供的一個(gè)方法,接收一個(gè)函數(shù)作為參數(shù),回調(diào)函數(shù)。
for...ofES6提供的遍歷器,除了可以遍歷數(shù)組,還支持類數(shù)組對象,甚至是字符串,其實(shí)就是繼承了Iterator接口的數(shù)據(jù)結(jié)構(gòu)都可以用for...of來遍歷。
for...of循環(huán)可以使用的范圍包括數(shù)組、Set 和 Map 結(jié)構(gòu)、某些類似數(shù)組的對象(比如arguments對象、DOM NodeList 對象)、后文的 Generator 對象,以及字符串。
我認(rèn)為,遍歷數(shù)組,使用for...of效果最佳。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/93053.html
摘要:淺拷貝深拷貝淺拷貝的問題如果父對象的屬性等于數(shù)組或另一個(gè)對象,那么實(shí)際上,子對象獲得的只是一個(gè)內(nèi)存地址,而不是真正拷貝,因此存在父對象被篡改的可能。 淺拷貝: function extendCopy(p) { var c = {}; for (var i in p) { c[i] = p[i]; } return c; } 深拷貝: function deepCopy(p...
摘要:前言里面淺拷貝和深拷貝是非常關(guān)鍵的知識點(diǎn),今天就來通過本文清楚的了解深淺拷貝以及該如何實(shí)現(xiàn)這兩種拷貝方式。對象的拷貝又分為淺拷貝和深拷貝。印證了上述所說的對于所有的基本類型,簡單的賦值已經(jīng)是實(shí)現(xiàn)了深拷貝。 前言 JavaScript里面淺拷貝和深拷貝是非常關(guān)鍵的知識點(diǎn),今天就來通過本文清楚的了解深淺拷貝以及該如何實(shí)現(xiàn)這兩種拷貝方式。 深淺拷貝的區(qū)別 拷貝:其實(shí)就是一個(gè)對象復(fù)制給另外...
摘要:二淺拷貝與深拷貝深拷貝和淺拷貝是只針對和這樣的引用數(shù)據(jù)類型的。淺拷貝是按位拷貝對象,它會(huì)創(chuàng)建一個(gè)新對象,這個(gè)對象有著原始對象屬性值的一份精確拷貝。對于字符串?dāng)?shù)字及布爾值來說不是或者對象,會(huì)拷貝這些值到新的數(shù)組里。 一、數(shù)據(jù)類型 數(shù)據(jù)分為基本數(shù)據(jù)類型(String, Number, Boolean, Null, Undefined,Symbol)和對象數(shù)據(jù)類型。 基本數(shù)據(jù)類型的特點(diǎn):直...
摘要:二淺拷貝與深拷貝深拷貝和淺拷貝是只針對和這樣的引用數(shù)據(jù)類型的。淺拷貝是按位拷貝對象,它會(huì)創(chuàng)建一個(gè)新對象,這個(gè)對象有著原始對象屬性值的一份精確拷貝。對于字符串?dāng)?shù)字及布爾值來說不是或者對象,會(huì)拷貝這些值到新的數(shù)組里。 一、數(shù)據(jù)類型 數(shù)據(jù)分為基本數(shù)據(jù)類型(String, Number, Boolean, Null, Undefined,Symbol)和對象數(shù)據(jù)類型。 基本數(shù)據(jù)類型的特點(diǎn):直...
摘要:在之前的文章專題之?dāng)?shù)據(jù)類型和類型檢測中我有講過,中的數(shù)據(jù)類型分為兩種,基本數(shù)據(jù)類型和引用數(shù)據(jù)類型,基本數(shù)據(jù)類型是保存在棧的數(shù)據(jù)結(jié)構(gòu)中的是按值訪問,所以不存在深淺拷貝問題。 前言 在開發(fā)過程中,偶爾會(huì)遇到這種場景,拿到一個(gè)數(shù)據(jù)后,你打算對它進(jìn)行處理,但是你又希望拷貝一份副本出來,方便數(shù)據(jù)對比和以后恢復(fù)數(shù)據(jù)。 那么這就涉及到了 JS 中對數(shù)據(jù)的深淺拷貝問題,所謂深淺拷貝,淺拷貝的意思就是,...
閱讀 1996·2021-09-09 09:33
閱讀 1118·2019-08-30 15:43
閱讀 2672·2019-08-30 13:45
閱讀 3313·2019-08-29 11:00
閱讀 863·2019-08-26 14:01
閱讀 3576·2019-08-26 13:24
閱讀 487·2019-08-26 11:56
閱讀 2696·2019-08-26 10:27