亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

JavaScript·隨記 深拷貝 vs. 淺拷貝

RyanQ / 1381人閱讀

摘要:而在這個(gè)運(yùn)算符的相關(guān)用例中,往往會(huì)涉及到其他知識(shí)點(diǎn),深拷貝和淺拷貝就是其中之一。即對(duì)象的淺拷貝會(huì)對(duì)主對(duì)象的值進(jìn)行拷貝,而該值有可能是一個(gè)指針,指向內(nèi)存中的同一個(gè)對(duì)象。,可以看到深拷貝和淺拷貝是對(duì)復(fù)制引用類(lèi)型變量而言的。

在ES6的系列文章中,基本都會(huì)提到Spread——擴(kuò)展運(yùn)算符(...)。而在這個(gè)運(yùn)算符的相關(guān)用例中,往往會(huì)涉及到其他知識(shí)點(diǎn),深拷貝淺拷貝就是其中之一。

背景知識(shí)

在討論深拷貝淺拷貝之前,我們先看一個(gè)例子:

let a = "hi";
b = a;
b = "hello";
console.log(a);
// "hi"

let arr1 = [1,2,3];
arr2 = arr1;
arr2[0] = 0;
console.log(arr1);
// [0,2,3]

可以看到:為不同的js變量復(fù)制值時(shí),結(jié)果是不同的。把字符串a的值復(fù)制給b,改變b的值不會(huì)影響a的值,而把數(shù)組arr1的值復(fù)制給arr2時(shí),改變arr2的值,arr1的值也跟著改變了。

這是因?yàn)閖s存在兩種不同數(shù)據(jù)類(lèi)型的值:基本類(lèi)型值引用類(lèi)型值。
在訪問(wèn)這兩種類(lèi)型的變量時(shí),其訪問(wèn)方式是不同的。在這里,先記一下結(jié)論:

基本數(shù)據(jù)類(lèi)型是按值訪問(wèn)的

引用數(shù)據(jù)類(lèi)型是按引用訪問(wèn)的
(實(shí)際上這種說(shuō)法并不嚴(yán)密,為便于理解,我們先這么記)

什么意思?
JavaScript不允許直接訪問(wèn)內(nèi)存中的位置,換句話說(shuō),不能直接操作對(duì)象的內(nèi)存空間。
因此,在操作對(duì)象時(shí),我們實(shí)際上是在操作對(duì)象的引用,而不是實(shí)際的對(duì)象

從一個(gè)變量向另一個(gè)變量復(fù)制值時(shí)(不管是復(fù)制基本類(lèi)型還是引用類(lèi)型),都會(huì)先為這個(gè)新變量分配一個(gè)空間,然后把該值復(fù)制到新創(chuàng)建的這個(gè)空間里。
不同的是,在復(fù)制引用類(lèi)型的值時(shí),實(shí)際上復(fù)制過(guò)去的是一個(gè)指針,示例圖如下:

在js中,除了7種基本類(lèi)型外,其他的都是引用類(lèi)型,比如Object,Array,Function,所以不難理解:

let obj1 = {name:"hx",age:18};
let obj2 = obj1;
obj2.age = 0;
console.log(obj1);
// {name:"hx",age:0}
“引用類(lèi)型的值是按引用訪問(wèn)的”不嚴(yán)密在:當(dāng)復(fù)制保存著對(duì)象的某個(gè)變量時(shí),操作的是對(duì)象的引用;而當(dāng)為對(duì)象添加屬性時(shí),操作的是實(shí)際的對(duì)象。 ——靈圖社區(qū)
深拷貝 vs. 淺拷貝

我們先來(lái)看一下概念:

淺拷貝:

被復(fù)制對(duì)象的所有變量都含有與原來(lái)的對(duì)象相同的值,而所有的對(duì)其他對(duì)象的引用仍然指向原來(lái)的對(duì)象。即對(duì)象的淺拷貝會(huì)對(duì)主對(duì)象的進(jìn)行拷貝,而該值有可能是一個(gè)指針,指向內(nèi)存中的同一個(gè)對(duì)象。

深拷貝:

深拷貝不僅將原對(duì)象的各個(gè)屬性逐個(gè)復(fù)制出去,而且將原對(duì)象各個(gè)屬性所包含的對(duì)象也依次采用深復(fù)制的方法遞歸復(fù)制到新對(duì)象上。所以對(duì)一個(gè)對(duì)象的修改完全不會(huì)影響到另一個(gè)對(duì)象。

OK,可以看到深拷貝淺拷貝是對(duì)“復(fù)制引用類(lèi)型變量”而言的。事實(shí)上,也只有在引用類(lèi)型中才有討論兩者區(qū)別的意義,對(duì)于基本數(shù)據(jù)類(lèi)型,怎么拷都是“深拷貝”。

淺拷貝就不說(shuō)了,=就是淺拷貝,那么如何實(shí)現(xiàn)深拷貝呢?
對(duì)于ObjectArray兩種類(lèi)型,我們分別舉例:

Object

首先是assign(),看代碼:

let obj = {name:"hx",age:18};
let copyObj = Object.assign({},obj);
copyObj.name = "H.Lucas";
console.log(obj);
// {name:"hx", age:18} 

Emm,貌似是深拷貝哈,那要是二維對(duì)象呢?

let obj = {name:"zj",attr:{age:18, nickname:"Z.Crystal"}}
let copyObj = Object.assign({},obj);
copyObj.attr.nickname = "erni";
console.log(obj);
// {name:"zj",attr:{age:18, nickname:"erni"}}

好吧,翻車(chē)了,看來(lái)assign只能實(shí)現(xiàn)一維對(duì)象的深拷貝。

然后是擴(kuò)展運(yùn)算符...,看代碼:

let obj = {name:"hx",age:18};
let copyObj = {...obj};
copyObj.name = "H.Lucas";
console.log(obj);
// {name:"hx", age:18} 

嗯,深拷貝哈,也來(lái)個(gè)二維對(duì)象試試:

let obj = {name:"zj",attr:{age:18, nickname:"Z.Crystal"}}
let copyObj = {...obj};
copyObj.attr.nickname = "erni";
console.log(obj);
// {name:"zj",attr:{age:18, nickname:"erni"}}

好吧,也炸了,看來(lái)都實(shí)現(xiàn)不了多維對(duì)象的深拷貝。

不過(guò)這里還是推崇一下...,為什么?看兩段代碼:

let obj1 = {a:1,b:2}
let obj2 = {b:3,c:4}
// 構(gòu)建一個(gè)新對(duì)象obj,值是obj1和obj2的集合
let obj = Object.assign(obj1,obj2)
obj.b = 100
console.log(obj1)
console.log(obj2)
// {a: 1, b: 100, c: 4}
// {b: 3, c: 4}
let obj1 = {a:1,b:2}
let obj2 = {b:3,c:4}
// 構(gòu)建一個(gè)新對(duì)象obj,值是obj1和obj2的集合
let obj = {...obj1,...obj2}
obj.b = 100
console.log(obj1)
console.log(obj2)
// {a: 1, b: 2}
// {b: 3, c: 4}

在第一段代碼中,執(zhí)行完Object.assign()時(shí),obj1已經(jīng)改變了,而且改變組合出來(lái)的obj時(shí),obj1還會(huì)再改變。實(shí)際上我只想組合出一個(gè)完全獨(dú)立的obj來(lái),可以肆意改變它,而不影響原始數(shù)據(jù)(想一下純函數(shù)的實(shí)現(xiàn),以及Redux等)。

Array

Emm,數(shù)組拷貝能想到哪些?
slice(),concat(),Array.from(),...
這里就不一個(gè)一個(gè)試了,先給出結(jié)論吧:
都只能實(shí)現(xiàn)一維數(shù)組的深拷貝

看個(gè)例子:

let arr1 = [1, 2], arr2 = [...arr1];
console.log(arr1); // [1, 2]
console.log(arr2); // [1, 2]
arr2[0] = 3;
console.log(arr1); // [1, 2]
console.log(arr2); // [3, 2]

let arr3 = [1, 2, [3, 4]], arr4 = [...arr3];
console.log(arr3); // [1, 2, [3, 4]]
console.log(arr4); // [1, 2, [3, 4]]
arr4[2][1] = 5; 
console.log(arr3); // [1, 2, [3, 5]]
console.log(arr4); // [1, 2, [3, 5]]

好吧,那js里到底有沒(méi)有不限條件的深拷貝方法呢?看下這個(gè):

let obj1 = {x:1, y:{z:1}};
let obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj2)
// {x:1, y:{z:1}}

// 改一下obj2,看看會(huì)不會(huì)影響obj1
obj2.y.z = 2;

console.log(obj1)
// {x:1, y:{z:1}}
// 可以,obj1沒(méi)有受到obj2的影響

簡(jiǎn)單粗暴吧?不過(guò)JSON.parse(JSON.stringify())也并不是萬(wàn)能的,比如對(duì)象的屬性是undefined,function()時(shí):

let obj1 = {
  x: 1,
  y: undefined,
  z: () => console.log("lalala")
};

let obj2 = JSON.parse(JSON.stringify(obj1));

console.log(obj2);
// {x: 1}
// 源對(duì)象的屬性y和z都丟失了,更別說(shuō)深拷貝了

那數(shù)組呢?有沒(méi)有不限條件的深拷貝方法,哪怕有個(gè)類(lèi)似的簡(jiǎn)單粗暴的不完全體也行啊。
據(jù)了解只有一種方法,建一個(gè)空數(shù)組,然后一級(jí)一級(jí)遍歷原數(shù)組并填充到里面吧。

Summary

JavaScript有兩種數(shù)據(jù)類(lèi)型:基本數(shù)據(jù)類(lèi)型引用數(shù)據(jù)類(lèi)型;

基本數(shù)據(jù)類(lèi)型:String,Number,Boolean,Undefined,Null,Symbol

引用數(shù)據(jù)類(lèi)型:Object,Array,F(xiàn)unction

JavaScript不允許直接訪問(wèn)內(nèi)存中的位置,因此我們操作的只是對(duì)象引用,而不是實(shí)際的對(duì)象;

深拷貝淺拷貝是針對(duì)引用數(shù)據(jù)類(lèi)型而言的;

JavaScript暫時(shí)還沒(méi)有實(shí)現(xiàn)多維數(shù)組/對(duì)象深拷貝的內(nèi)置方法(還是說(shuō),有,但是我不知道。。)

對(duì)了,補(bǔ)充一個(gè)知識(shí)點(diǎn):
有人說(shuō),我家=也可以實(shí)現(xiàn)一級(jí)深拷貝啊,你看:

let arr1 = {a:1,b:2};
arr2 = arr1;
arr2 = {a:0,b:1};
console.log(arr2); // {a:0, b:2}
console.log(arr1); // {a:1, b:2}

額。。不帶你這么玩的。。
arr2 = {a:0,b:1}; vs. arr2.a = 0;
這兩種操作可不是一碼事。。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/104034.html

相關(guān)文章

  • javascript拷貝VS拷貝

    摘要:深拷貝淺拷貝本文主要對(duì)深拷貝淺拷貝的解釋及實(shí)現(xiàn)做一下簡(jiǎn)單記錄。之所以會(huì)有深拷貝與淺拷貝之分,是因?yàn)椴煌瑪?shù)據(jù)類(lèi)型的數(shù)據(jù)在內(nèi)存中的存儲(chǔ)區(qū)域不一樣。但注意,只能做一層屬性的淺拷貝。 深拷貝VS淺拷貝 本文主要對(duì)深拷貝&淺拷貝的解釋及實(shí)現(xiàn)做一下簡(jiǎn)單記錄。原文鏈接,歡迎star。 之所以會(huì)有深拷貝與淺拷貝之分,是因?yàn)椴煌瑪?shù)據(jù)類(lèi)型的數(shù)據(jù)在內(nèi)存中的存儲(chǔ)區(qū)域不一樣。 堆和棧是計(jì)算機(jī)中劃分出來(lái)用來(lái)存儲(chǔ)的...

    Nekron 評(píng)論0 收藏0
  • 拷貝 vs 拷貝

    摘要:那么如何切斷和之間的關(guān)系呢,可以拷貝一份的數(shù)據(jù),根據(jù)拷貝的層級(jí)不同可以分為淺拷貝和深拷貝,淺拷貝就是只進(jìn)行一層拷貝,深拷貝就是無(wú)限層級(jí)拷貝。 深拷貝 vs 淺拷貝 深拷貝和淺拷貝都是針對(duì)的引用類(lèi)型,JS中的變量類(lèi)型分為值類(lèi)型(基本類(lèi)型)和引用類(lèi)型;對(duì)值類(lèi)型進(jìn)行復(fù)制操作會(huì)對(duì)值進(jìn)行一份拷貝,而對(duì)引用類(lèi)型賦值,則會(huì)進(jìn)行地址的拷貝,最終兩個(gè)變量指向同一份數(shù)據(jù)。 // 基本類(lèi)型 var a = ...

    sugarmo 評(píng)論0 收藏0
  • 拷貝

    摘要:深復(fù)制實(shí)現(xiàn)代碼如下第一種方法通過(guò)遞歸解析解決第二種方法通過(guò)解析解決作者六師兄鏈接原生深拷貝的實(shí)現(xiàn)處理未輸入新對(duì)象的情況通過(guò)方法構(gòu)造新的對(duì)象 深淺拷貝針對(duì)的是 對(duì)象類(lèi)型,如果是字符串的數(shù)組用[...arr],還是不會(huì)影響 要區(qū)分針對(duì)數(shù)組的深淺拷貝(默認(rèn)情況為里面沒(méi)有對(duì)象的數(shù)組),與針對(duì)對(duì)象的深淺拷貝 JavaScript數(shù)組深拷貝和淺拷貝的兩種方法 let a1 = [1, 2]; ...

    Karrdy 評(píng)論0 收藏0
  • 拷貝拷貝

    摘要:二淺拷貝與深拷貝深拷貝和淺拷貝是只針對(duì)和這樣的引用數(shù)據(jù)類(lèi)型的。淺拷貝是按位拷貝對(duì)象,它會(huì)創(chuàng)建一個(gè)新對(duì)象,這個(gè)對(duì)象有著原始對(duì)象屬性值的一份精確拷貝。對(duì)于字符串?dāng)?shù)字及布爾值來(lái)說(shuō)不是或者對(duì)象,會(huì)拷貝這些值到新的數(shù)組里。 一、數(shù)據(jù)類(lèi)型 數(shù)據(jù)分為基本數(shù)據(jù)類(lèi)型(String, Number, Boolean, Null, Undefined,Symbol)和對(duì)象數(shù)據(jù)類(lèi)型。 基本數(shù)據(jù)類(lèi)型的特點(diǎn):直...

    hzc 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<