淺拷貝與深拷貝的區別。如何實現深拷貝。

2021-09-24 01:17:05 字數 4777 閱讀 7675

關於拷貝應該是大家面試中經常被問到的問題,特此總結一下,為以後積累經驗。

鞏固拷貝之前必須先回顧下資料的分類,知道其儲存的位置。

基本資料型別:

1)分類 (string number boolean undefined null symbol)

2)特點(資料存在棧記憶體中)

引用資料型別:

1)分類 (object)

2)特點(棧記憶體中存的是指向堆記憶體中資料物件的乙個位址值,可以理解成是乙個指標。當尋找引用型別的值時,會先在棧記憶體中找到指標,然後堆記憶體中找到該引用物件。)

何為拷貝:簡易理解為重新複製乙份資料。

淺拷貝和深拷貝主要針對引用型別資料而言。基本型別資料都是拷貝的棧記憶體中的值,改變拷貝後的值對原值不會產生影響。

賦值:

不產生新物件,當我們把乙個物件賦值給乙個新的變數時,賦的其實是該物件的在棧中的位址,而不是堆中的資料。兩個物件指向同乙個儲存空間,無論哪個物件發生改變,其實都是改變的儲存空間的內容。

var a =1;

var b = a;

b =2

;console.

log(a)

//1console.

log(b)

//2var obj =

var obj1 = obj

obj1.name =

'小明1'

obj1.eat[1]

=[1,

1]console.

log(

'obj'

,obj)

//console.

log(

'obj1'

,obj1)

//

淺拷貝:

產生新物件,如果被拷貝物件的屬性中有引用型別的值,則拷貝的是資料在堆記憶體中的位址值,通過拷貝後得到的變數修改資料,源物件中的資料發生改變

即淺拷貝只複製物件的第一層屬性。

var obj2 =

var obj3 =

clone

(obj2)

obj3.name =

'小明1'

obj3.eat[1]

=[1,

1]console.

log(

'obj2'

,obj2)

//obj2

console.

log(

'obj3'

,obj3)

//obj3

function

clone

(src)

for(

var prop in src)

}return cloneobj

}

深拷貝:

產生新物件, 如果被拷貝物件的屬性中有引用型別的值,拷貝得是資料在堆記憶體中的值,通過拷貝後得到的變數修改資料,源物件中的資料不發生改變

即深拷貝可以對物件的屬性進行遞迴複製;

//拷貝物件

var obj4 =

var obj5 =

deepclone

(obj2)

obj5.name =

'小明1'

obj5.eat[1]

=[1,

1]console.

log(

'obj4'

,obj4)

//obj4

console.

log(

'obj5'

,obj5)

//obj5

//拷貝陣列

let arr =[1

,2,3

,4,[

5,6]

]let arr1 =

deepclone

(arr)

arr1[4]

=[1,

1]console.

log(

'arr'

,arr)

//arr [ 1, 2, 3, 4, [ 5, 6 ] ]

console.

log(

'arr1'

,arr1)

//arr1 [ 1, 2, 3, 4, [ 1, 1 ] ]

function

deepclone

(src)

for(

var prop in src)

else}}

return cloneobj

}

本質區別:修改拷貝後的物件的值,是否影響源物件。

1,object.assign()

const h =

}const i = object.

assign

(,h)

i.eat.food =

'noodle'

console.

log(h)

// }

console.

log(i)

// }

2,array.prototype.concat()

const arr2 =[1

,2,3

,,[2

,2]]

const arr3 = arr2.

concat()

arr3[3]

.name =

'小虹'

arr3[4]

=[1,

1]console.

log(arr2)

//[ 1, 2, 3, ,[2,2] ]

console.

log(arr3)

//[ 1, 2, 3, ,[1,1] ]

3,for in(可以拷貝原型上的屬性)

obj.prototype.run =

const obj1 =

newobj(18

,['red'])

const obj2 =

for(

let i in obj1)

obj1.age =

20obj1.eat.food =

'noodle'

obj1.color.

push

('green'

)console.

log(obj1)

// }

console.

log(obj2)

//,run: }

console.

log(obj1.run)

//console.

log(obj2.run)

//

4,…擴充套件運算子(不可以拷貝原型上的屬性)

function

obj(age,color)

}obj.prototype.run =

const obj1 =

newobj(18

,['red'])

const obj2 =

obj1.age =

20obj1.eat.food =

'noodle'

obj1.color.

push

('green'

)console.

log(obj1)

// }

console.

log(obj2)

// }

console.

log(obj1.run)

//console.

log(obj2.run)

//undefined

json.parse(json.stringify())

const arr4 = [1,2,3,]

const arr5 = json.parse(json.stringify(arr4))

arr5[3].name = 'json'

console.log(arr4) //[ 1, 2, 3, ]

console.log(arr5) //[ 1, 2, 3, ]

封裝遞迴的方法(見上圖)

函式庫lodash

var _ =

require

('lodash'

)const arr6 =[1

,2,3

,]const arr7 = _.

clonedeep

(arr6)

arr7[3]

.name =

'lodash'

console.

log(arr6)

console.

log(arr7)

js深拷貝與淺拷貝區別,如何實現深拷貝

首先我們需要弄清楚什麼是淺拷貝,其實我個人覺得淺拷貝從性質上和事件冒泡一樣,當出現這種事件時就代表出問題了 首先要看看js資料的儲存空間 按儲存空間我們可以簡單將js資料分為兩大類 基礎變數,整個存在棧中。還有一種是匯入型別 例如 陣列 json物件 null等 他們的 名相當於乙個指標,而真正的變...

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

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

實現淺拷貝與深拷貝

js包含基本資料型別與引用資料型別兩種不同的資料型別的值,深拷貝與淺拷貝的概念只存在於引用資料型別。對於引用型別,淺拷貝是拷貝了指向這個物件堆記憶體的指標,是拷貝了對原物件引用,深拷貝是拷貝了該物件的所有屬性到乙個新的物件,若是原物件的某屬性依然引用了其他物件,那麼需要將原物件引用的其他物件一併進行...