前端的深拷貝和淺拷貝 前端面試 深拷貝和淺拷貝

2021-10-13 00:14:57 字數 3077 閱讀 9288

面試題目:如何實現對乙個陣列或物件的淺拷貝和深拷貝?

wtf,複製還分兩種,第一次遇到這種問題的時候很是無語呢,先來看看一般的答案的理解。

淺拷貝是只拷貝一層,深層次的物件級別就只拷貝引用。 深拷貝是拷貝多層,每一級別的資料都拷貝出來。也就是說,基本資料型別其實不存在深淺拷貝的問題,只有物件和陣列才存在深淺拷貝的問題。

主要解決的是什麼問題呢?你去買房子,看中一套不錯要了,然後中介給你列印了乙份合同,你簽字付錢。過一段時間去看,哎呀我去,怎麼裝修了?另外乙個人也拿著同樣有合同、付款憑證。我以為是我買的房子,結果中介一房兩賣,別人也能搞。這怎麼行?

js資料型別

js分為基本資料型別和複雜資料型別。

基本資料型別包括:string、number、boolean、null、undefined

複雜(引用)型別包括:object、array、function

在開發過程中,經常使用 typeof 來檢測資料型別。預設var宣告的時候,如果不進行賦值,型別就是undefined。布林值是boolean只有 true,false兩種值。

宣告的時候用的null,這時候代表空物件,使用typeof檢測的時候,顯示是object。

js記憶體管理

js**執行的時候,資料都要寫入記憶體進行呼叫的,而不同的資料型別在記憶體中存放的方式是不一樣的。

基本資料型別是儲存在棧資料空間中,複雜資料型別是儲存在堆資料空間中的,而對資料空間不能直接訪問,需要棧這邊進行位置指引。

乙個不是很恰當的比喻就是記憶體相當於倉庫。

倉庫裡面分了兩個區域,一邊是都是小格仔,另一邊都是大貨櫃。簡單資料型別比如你的一本書,你的乙份賬單什麼的就直接放在小格仔裡面就好了。

另外你有一屋子書和一屋子的賬單,小格仔放不下。你就租了乙個小格仔和乙個倉庫。小格仔裡面放著倉庫的鑰匙和倉庫的位置,倉庫裡面放東西。

實際的記憶體讀取方式也類似。要找自己的小格仔,你就要從上到下挨著找。想要找自己貨櫃裡面的東西,還是需要先去小格仔裡面找到存放鑰匙和位置的格仔,找到以後直接去找貨櫃。

下圖是淺拷貝和深拷貝

再沒有了解到深拷貝和淺拷貝知識的時候,一般拷貝就是從新賦值。宣告個資料直接用另外乙個物件賦值。這個就算是淺拷貝。

當遇到複雜物件的時候,複製的只是物件的指標,並沒有重新開闢大的空間進行複製。這時候造成的影響就是對兩個指標進行資料操作的時候,操作的是同乙個資料內容,相互之間是受影響的。

而深拷貝就是需要連指標到內容都進行複製,兩個指標指向兩個空間的內容。各自操作已經不受影響。

淺拷貝的實現方式

淺拷貝的複製就是直接複製賦值就可以了。

方法一:

function ******clone(initalobj) ; for ( var i in initalobj) return obj;}var obj = , c:["bob", "tom", "jenny"], d:function() }var cloneobj = ******clone(obj); console.log(cloneobj.b); console.log(cloneobj.c);console.log(cloneobj.d);cloneobj.b.a = "changed";cloneobj.c = [1, 2, 3];cloneobj.d = function() ;console.log(obj.b);console.log(obj.c);console.log(obj.d);自行執行檢視下變化及原因。

方法二: object.assign是es6的新函式。object.assign() 方法可以把任意多個的源物件自身的可列舉屬性拷貝給目標物件,然後返回目標物件。但是 object.assign() 進行的是淺拷貝,拷貝的是物件的屬性的引用,而不是物件本身。

object.assign(target, ...sources)var obj = };var initalobj = object.assign({}, obj);initalobj.a.a = "changed";console.log(obj.a.a); // "changed"需要注意的是:

object.assign()可以處理一層的深度拷貝,如下:

var obj1 = ;var obj2 = object.assign({}, obj1);obj2.b = 100;console.log(obj1);//

如果要複製的物件只有一層,物件裡面的元素全是基本元素的話,前面的淺拷貝案例其實就完成了深拷貝的功能。我們重點說一下多層物件。

1.通過json轉換 用json.stringify把物件轉成字串,再用json.parse把字串轉成新的物件。

但是這種方法也有不少壞處,譬如它會拋棄物件的constructor。也就是深拷貝之後,不管這個物件原來的建構函式是什麼,在深拷貝之後都會變成object。並且只能處理常見的number, string, boolean, array, 扁平物件等這些能被json表示的資料結構。regexp物件是無法通過這種方式深拷貝。

2.遞迴拷貝

function deepclone(initalobj, finalobj) ; for (var i in initalobj) if (typeof prop === 'object') ; arguments.callee(prop, obj[i]); } else } return obj;}遞迴拷貝就是將物件逐層解開進行剖析,逐層新建物件,逐層複製,知道最深處的所有簡單資料都複製上。

但是要注意要注意物件引用物件的情況,會掉入死迴圈。

3.使用object.create()方法 直接使用var newobj = object.create(oldobj),可以達到深拷貝的效果。

function deepclone(initalobj, finalobj) ; for (var i in initalobj) if (typeof prop === 'object') else } return obj;}小案例

之前在進行公司vue專案開發的過程中,由於需要將富文字編輯器抽離成為乙個單獨的元件,然後將內容的物件傳入進去。如果按照傳統的vue元件開發的流程,肯定是要接收傳入、賦值給本元件、本元件編輯器修改、修改完畢的內容再進行emit外傳,然後元件外部接受,進一步處理。

但是由於vue元件之間淺拷貝的特性,其實傳入的物件修改之後,外部元件直接取值拿到的就是最新的值。

也是因為這個發現才對深拷貝和淺拷貝有了更加深入的了解。

前端面試之淺拷貝深拷貝

淺拷貝 定義 對於字串型別,淺複製是對值的複製,對於物件來說,淺複製是對物件位址的複製,並沒 有開闢新的棧,也就是複製的結果是兩個物件指向同乙個位址,修改其中乙個物件的屬性,則另乙個物件的屬性也會改變 方法 1,object.assign es6中拷貝物件的方法,接受的第乙個引數是拷貝的目標targ...

前端面試經常問到的淺拷貝和深拷貝

1.深拷貝 淺拷貝定義概述 淺拷貝的時候如果目標是基本資料型別,就如同直接賦值那種,會拷貝其本身,如果目標是物件,那麼對於淺拷貝而言就只能拷貝其引用,原物件改變,拷貝物件也會隨之改變 但是深拷貝就會拷貝多層,即使是巢狀了物件,也會都拷貝出來。深拷貝在計算機中開闢了一塊記憶體位址用於存放複製的物件,原...

前端的深拷貝和淺拷貝 深拷貝與淺拷貝的區別

淺拷貝的方式 淺拷貝1 var obj var newobj obj newobj.name 李四 console.log obj console.log newobj 淺拷貝2 object.assgin 引數1 目標物件 引數2 任意多個物件 如果物件是多層的話 var obj var obj1...