摘要:如果值為或,它將創(chuàng)建并返回一個(gè)空對(duì)象,否則,它將返回一個(gè)對(duì)應(yīng)于給定值的對(duì)象。如果該值已經(jīng)是一個(gè)對(duì)象,它將返回該值。此方法不會(huì)更改現(xiàn)有的數(shù)組,而是返回一個(gè)新的數(shù)組。所以我們可以使用遞歸實(shí)現(xiàn)一個(gè)下面就直接貼代碼了,略啰嗦,歡迎拍磚
Object.assign 是什么?
此處直接復(fù)制mdn文檔的內(nèi)容如下:
The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.
翻譯一下也就是:
Object.assign()方法用于將所有可枚舉屬性的值從一個(gè)或多個(gè)源對(duì)象復(fù)制到目標(biāo)對(duì)象。它會(huì)返回目標(biāo)對(duì)象。
為了便于理解,此處貼出mdn的對(duì)Object.assign的polyfill
if (typeof Object.assign != "function") { // Must be writable: true, enumerable: false, configurable: true Object.defineProperty(Object, "assign", { value: function assign(target, varArgs) { // .length of function is 2 "use strict"; if (target == null) { // TypeError if undefined or null throw new TypeError("Cannot convert undefined or null to object"); } var to = Object(target); for (var index = 1; index < arguments.length; index++) { var nextSource = arguments[index]; if (nextSource != null) { // Skip over if undefined or null for (var nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { to[nextKey] = nextSource[nextKey]; } } } } return to; }, writable: true, configurable: true }); }
其中的Object構(gòu)造函數(shù)為給定的值創(chuàng)建一個(gè)對(duì)象包裹器。如果值為null或undefined,它將創(chuàng)建并返回一個(gè)空對(duì)象,否則,它將返回一個(gè)Type對(duì)應(yīng)于給定值的對(duì)象。如果該值已經(jīng)是一個(gè)對(duì)象,它將返回該值。
舉個(gè)栗子?
Object(1) // Number {1} Object("") // String {"", length: 0} Object(false) // Boolean {false}
從polyfill的代碼不難看出,Object.assign 就是將所傳參數(shù)當(dāng)中的對(duì)象的可枚舉屬性的值覆蓋到第一個(gè)對(duì)象上,那么由于js當(dāng)中的object,array是引用類型,所以對(duì)與對(duì)象,數(shù)組的覆蓋其實(shí)只是覆蓋了對(duì)數(shù)組,對(duì)象的引用,也即 淺copy
mdn栗子來一枚
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 }如何實(shí)現(xiàn)深copy?
來個(gè)redux 當(dāng)中reducer 嵌套數(shù)據(jù)更新的栗子?
add(state, { payload: todo }) { const todos = state.a.b.todos.concat(todo); const b = Object.assign({},state.a.b,{todos}) const a = Object.assign({},state.a,); return Object({},state,{a}); },
上面的栗子當(dāng)中concat()方法用于合并兩個(gè)或多個(gè)數(shù)組。此方法不會(huì)更改現(xiàn)有的數(shù)組,而是返回一個(gè)新的數(shù)組??梢岳斫鉃槔胏oncat方法創(chuàng)建了一個(gè)新的todos數(shù)組,這樣就可以避免對(duì)數(shù)據(jù)的修改影響到了舊的todos數(shù)組,然后將新的todos數(shù)組使用Object.assign 給新的b,以此,僅僅實(shí)現(xiàn)了sate對(duì)象中將深層次的todos的一個(gè)‘深copy’。
但是如果state還有其他的屬性的值為對(duì)象或者數(shù)組,簡(jiǎn)單的使用Object.assign 只是復(fù)制了一個(gè)引用。所以在寫reducer的時(shí)候需要盡量避免state嵌套的太深,為了安全,我們可以使用 updeep來更新數(shù)據(jù),或者直接使用不可變數(shù)據(jù),此處不再多說,繼續(xù)探討Object.assign.
前面探討了對(duì)象當(dāng)中單個(gè)屬性值的深copy,但是如果有多個(gè)值,怎么辦呢?一個(gè)一個(gè)手動(dòng)找出來?當(dāng)然不行啊,這樣一點(diǎn)兒也不好玩兒 為了實(shí)現(xiàn)一個(gè)deepCopy,我們先簡(jiǎn)單了解一下js的數(shù)據(jù)類型:值類型:數(shù)值、布爾值、null、undefined。
基本類型值是指在棧內(nèi)存保存的簡(jiǎn)單數(shù)據(jù)段,在復(fù)制基本類型值的時(shí)候,會(huì)開辟出一個(gè)新的內(nèi)存空間,將值復(fù)制到新的內(nèi)存空間,舉個(gè)栗子:
var a = 1; var b = a; a = 2; console.log(a);//輸出2; console.log(b);//輸出1;引用類型:對(duì)象、數(shù)組、函數(shù)等。
用類型值是保存在堆內(nèi)存中的對(duì)象,變量保存的只是指向該內(nèi)存的地址,在復(fù)制引用類型值的時(shí)候,其實(shí)只復(fù)制了指向該內(nèi)存的地址,舉個(gè)栗子:
var a={b:1} var a2 = a; a2.b = 2; console.log(a) // 輸出 {b: 2}deepCopy
了解了js的數(shù)組類型之后,那么實(shí)現(xiàn)一個(gè)深copy其實(shí)主要就是解決引用類型的copy,數(shù)組和對(duì)象無限往下拆,最終其屬性也是值類型組成的。所以我們可以使用遞歸實(shí)現(xiàn)一個(gè)deepCopy,下面就直接貼代碼了,略啰嗦,歡迎?拍磚
function detectType(source) { return Object.prototype.toString .call(source) .split(/[[,s,]]/)[2] .toLowerCase(); } function deepCopy(source, copyDeep) { var type = detectType(source); if (!(type === "object" || type === "array")) { return source; } var newObject = type === "array" ? source.slice() :Object.assign({}, source); if (!copyDeep) { return newObject; } Object.keys(newObject).forEach(function (key) { newObject[key] = deepCopy(newObject[key], true); }); return newObject; }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/107322.html
摘要:而在這個(gè)運(yùn)算符的相關(guān)用例中,往往會(huì)涉及到其他知識(shí)點(diǎn),深拷貝和淺拷貝就是其中之一。即對(duì)象的淺拷貝會(huì)對(duì)主對(duì)象的值進(jìn)行拷貝,而該值有可能是一個(gè)指針,指向內(nèi)存中的同一個(gè)對(duì)象。,可以看到深拷貝和淺拷貝是對(duì)復(fù)制引用類型變量而言的。 在ES6的系列文章中,基本都會(huì)提到Spread——擴(kuò)展運(yùn)算符(...)。而在這個(gè)運(yùn)算符的相關(guān)用例中,往往會(huì)涉及到其他知識(shí)點(diǎn),深拷貝和淺拷貝就是其中之一。 背景知識(shí) 在討...
摘要:前言,顧名思義即遠(yuǎn)程過程調(diào)用,可以說是分部式應(yīng)用的基礎(chǔ),也是概念中的核心部分。對(duì)于來說,可以分為之間的調(diào)用與和其他平臺(tái)之間的調(diào)用。和分別代表了這兩種模式。 前言 RPC,顧名思義即遠(yuǎn)程過程調(diào)用,可以說是分部式WEB應(yīng)用的基礎(chǔ),也是SOA概念中的核心部分。對(duì)于J2EE來說,可以分為JVM之間的調(diào)用與和其他平臺(tái)之間的調(diào)用。前者主要是RMI,而后者則五花八門,比如Apache的Thrift...
閱讀 1840·2023-04-25 15:51
閱讀 2521·2021-10-13 09:40
閱讀 2159·2021-09-23 11:22
閱讀 3262·2019-08-30 14:16
閱讀 2683·2019-08-26 13:35
閱讀 1876·2019-08-26 13:31
閱讀 897·2019-08-26 11:39
閱讀 2761·2019-08-26 10:33