這篇文章將為大家詳細(xì)講解有關(guān)Object.assign如何在JavaScript中使用,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
東城網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)公司!從網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站開發(fā)等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營維護(hù)。成都創(chuàng)新互聯(lián)公司成立于2013年到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)公司。深拷貝與淺拷貝
在 JavaScript 中,對(duì)于基本數(shù)據(jù)類型(undefined、null、boolean、number、string)來說,在變量中存儲(chǔ)的就是這個(gè)變量本身的值,復(fù)制是對(duì)值的復(fù)制,不存在深淺之說。但C系語言的共同特點(diǎn)中有,存儲(chǔ)引用類型(對(duì)象),實(shí)際中在變量里存的是它的地址。因此對(duì) JavaScript 中的復(fù)雜數(shù)據(jù)類型(object)來說,也會(huì)有淺拷貝和深拷貝的概念:淺拷貝指兩個(gè)不同的變量存的是同一個(gè)對(duì)象的地址,即兩個(gè)變量指向同一塊內(nèi)存區(qū)域;深拷貝則是重新分配了一塊內(nèi)存區(qū)域來存儲(chǔ)復(fù)制后的對(duì)象,兩個(gè)變量存的是真正的兩個(gè)互不影響的變量。
p.s. 有些資料認(rèn)為淺拷貝是重新分配內(nèi)存,并把原對(duì)象中的各個(gè)屬性進(jìn)行依次復(fù)制而不進(jìn)行遞歸復(fù)制屬性值是對(duì)象的情況,也就是只復(fù)制對(duì)象的最外面一層。本文將這種情況歸于“深拷貝和淺拷貝的中間情況”,文中以“是否劃分新的內(nèi)存”為界限劃分深淺拷貝,這種劃分方式與 C/C++、C#、Java 等C系語言保持概念一致。
淺拷貝在JavaScript中的實(shí)現(xiàn)
淺拷貝在js中很簡單,例如:
let objA = { name: '對(duì)象A', content: '我是A' }; let copyA = objA; console.log(objA.name); // ==> "對(duì)象A" console.log(copyA.name); // ==> "對(duì)象A"
如此即得到了objA的一份淺拷貝copyA,由于指向的是同一個(gè)對(duì)象,因此在修改objA的同時(shí)也是修改了copyA,反之亦然。
Object.assign()
Object.assign(target, …sources) MDN上對(duì)該方法的描述是 將所有可枚舉屬性的值從一個(gè)或多個(gè)源對(duì)象復(fù)制到目標(biāo)對(duì)象,String類型和 Symbol 類型的屬性都會(huì)被拷貝, 并且該方法會(huì)忽略值為 或者 undefined 的源對(duì)象。例如:
var o1 = { a: 1 }; var o2 = { [Symbol('foo')]: 2 }; var obj = Object.assign({}, o1, o2); console.log(obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox) Object.getOwnPropertySymbols(obj); // [Symbol(foo)]
Object.assign 的深拷貝與淺拷貝
注意前面說的是可枚舉屬性,這是一個(gè)介于完全的深拷貝和完全的淺拷貝之間的方法:如果我們把它的第一個(gè)參數(shù)target設(shè)置為一個(gè)空對(duì)象 {},同時(shí)保證剩余的源對(duì)象sources中的屬性類型不包含引用類型,則該方法的返回值就是一個(gè)與源對(duì)象相同的但并不在同一塊內(nèi)存空間另一個(gè)對(duì)象,即獲得了源對(duì)象的深拷貝。但是,如果源對(duì)象的屬性中包含某個(gè)對(duì)象,也就是這個(gè)屬性的值指向某個(gè)對(duì)象,就像下面這樣:
var obj = { name: 'obj name', content: { a: 1, b: 2 } };
則使用 Object.assign({}, obj)
時(shí),返回的目標(biāo)對(duì)象中的content屬性與源對(duì)象obj中的content屬性指向的同一塊內(nèi)存區(qū)域,即對(duì)obj下的content屬性進(jìn)行了淺拷貝。因此針對(duì)深拷貝,需要使用其他方法,比如自己實(shí)現(xiàn)一個(gè)深拷貝的方法,或者使用 JSON.parse(JSON.stringify(obj))
, 因?yàn)?Object.assign()
拷貝的是屬性值。
Object.assign 的屬性覆蓋
如果目標(biāo)對(duì)象中的屬性具有相同的鍵,則屬性將被源中的屬性覆蓋。后來的源的屬性將類似地覆蓋早先的屬性,因此可以用來合并對(duì)象(常用的一個(gè)場景是使用reducers更新React應(yīng)用的狀態(tài))。
var o1 = { a: 1, b: 1, c: 1 }; var o2 = { b: 2, c: 2 }; var o3 = { c: 3 }; var obj = Object.assign({}, o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 }
關(guān)于對(duì)象的繼承屬性和不可枚舉屬性
前文有提到,Object.assign
拷貝的是對(duì)象的可枚舉屬性,該方法使用源對(duì)象的 [[Get]]
和目標(biāo)對(duì)象的 [[Set]]
,所以它會(huì)調(diào)用相關(guān) getter
和 setter
。因此,不如說它是分配屬性,而不僅僅是復(fù)制或定義新的屬性。如果合并源包含 getter,這可能使其不適合將新屬性合并到原型中,將屬性定義(包括其可枚舉性)復(fù)制到原型應(yīng)使用Object.getOwnPropertyDescriptor()
和 Object.defineProperty()
,因此 Object.assign
不能拷貝對(duì)象的繼承屬性,例如:
var obj = Object.create({foo: 1}, { // foo 是個(gè)繼承屬性。 bar: { value: 2 // bar 是個(gè)不可枚舉屬性。 }, baz: { value: 3, enumerable: true // baz 是個(gè)自身可枚舉屬性。 } }); var copy = Object.assign({}, obj); console.log(copy); // { baz: 3 }
當(dāng)源對(duì)象是原始數(shù)據(jù)類型時(shí)
ECMAScript 有 5 種原始類型(primitive type): Undefined
、Null
、Boolean
、Number
和 String
。當(dāng)Object.assign
的源對(duì)象是原始類型時(shí),源對(duì)象會(huì)被包裝成“對(duì)象”,對(duì)應(yīng)的鍵是它在源對(duì)象中的索引值:
var v1 = "abc"; var v2 = true; var v3 = 10; var v4 = Symbol("foo") var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); // 原始類型會(huì)被包裝,null 和 undefined 會(huì)被忽略。 // 注意,只有字符串的包裝對(duì)象才可能有自身可枚舉屬性。 console.log(obj); // { "0": "a", "1": "b", "2": "c" }
當(dāng)拷貝過程中發(fā)生異常時(shí)
在出現(xiàn)錯(cuò)誤的情況下,例如,如果屬性不可寫,會(huì)引發(fā)TypeError,異常會(huì)打斷后續(xù)的拷貝任務(wù)。如果在引發(fā)錯(cuò)誤之前添加了任何屬性,則可以更改target對(duì)象。
var target = Object.defineProperty({}, "foo", { value: 1, writable: false }); // target 的 foo 屬性是個(gè)只讀屬性。 Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4}); // TypeError: "foo" is read-only // 注意這個(gè)異常是在拷貝第二個(gè)源對(duì)象的第二個(gè)屬性時(shí)發(fā)生的。 console.log(target.bar); // 2,說明第一個(gè)源對(duì)象拷貝成功了。 console.log(target.foo2); // 3,說明第二個(gè)源對(duì)象的第一個(gè)屬性也拷貝成功了。 console.log(target.foo); // 1,只讀屬性不能被覆蓋,所以第二個(gè)源對(duì)象的第二個(gè)屬性拷貝失敗了。 console.log(target.foo3); // undefined,異常之后 assign 方法就退出了,第三個(gè)屬性是不會(huì)被拷貝到的。 console.log(target.baz); // undefined,第三個(gè)源對(duì)象更是不會(huì)被拷貝到的。
關(guān)于Object.assign如何在JavaScript中使用就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。