摘要:如果值為或,它將創建并返回一個空對象,否則,它將返回一個對應于給定值的對象。如果該值已經是一個對象,它將返回該值。此方法不會更改現有的數組,而是返回一個新的數組。所以我們可以使用遞歸實現一個下面就直接貼代碼了,略啰嗦,歡迎拍磚
Object.assign 是什么?
此處直接復制mdn文檔的內容如下:
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()方法用于將所有可枚舉屬性的值從一個或多個源對象復制到目標對象。它會返回目標對象。
為了便于理解,此處貼出mdn的對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構造函數為給定的值創建一個對象包裹器。如果值為null或undefined,它將創建并返回一個空對象,否則,它將返回一個Type對應于給定值的對象。如果該值已經是一個對象,它將返回該值。
舉個栗子?
Object(1) // Number {1} Object("") // String {"", length: 0} Object(false) // Boolean {false}
從polyfill的代碼不難看出,Object.assign 就是將所傳參數當中的對象的可枚舉屬性的值覆蓋到第一個對象上,那么由于js當中的object,array是引用類型,所以對與對象,數組的覆蓋其實只是覆蓋了對數組,對象的引用,也即 淺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 }如何實現深copy?
來個redux 當中reducer 嵌套數據更新的栗子?
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,{b}); return Object({},state,{a}); },
上面的栗子當中concat()方法用于合并兩個或多個數組。此方法不會更改現有的數組,而是返回一個新的數組。可以理解為利用concat方法創建了一個新的todos數組,這樣就可以避免對數據的修改影響到了舊的todos數組,然后將新的todos數組使用Object.assign 給新的b,以此,僅僅實現了sate對象中將深層次的todos的一個‘深copy’。
但是如果state還有其他的屬性的值為對象或者數組,簡單的使用Object.assign 只是復制了一個引用。所以在寫reducer的時候需要盡量避免state嵌套的太深,為了安全,我們可以使用 updeep來更新數據,或者直接使用不可變數據,此處不再多說,繼續探討Object.assign.
前面探討了對象當中單個屬性值的深copy,但是如果有多個值,怎么辦呢?一個一個手動找出來?當然不行啊,這樣一點兒也不好玩兒 為了實現一個deepCopy,我們先簡單了解一下js的數據類型:值類型:數值、布爾值、null、undefined。
基本類型值是指在棧內存保存的簡單數據段,在復制基本類型值的時候,會開辟出一個新的內存空間,將值復制到新的內存空間,舉個栗子:
var a = 1; var b = a; a = 2; console.log(a);//輸出2; console.log(b);//輸出1;引用類型:對象、數組、函數等。
用類型值是保存在堆內存中的對象,變量保存的只是指向該內存的地址,在復制引用類型值的時候,其實只復制了指向該內存的地址,舉個栗子:
var a={b:1} var a2 = a; a2.b = 2; console.log(a) // 輸出 {b: 2}deepCopy
了解了js的數組類型之后,那么實現一個深copy其實主要就是解決引用類型的copy,數組和對象無限往下拆,最終其屬性也是值類型組成的。所以我們可以使用遞歸實現一個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; }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107322.html
摘要:而在這個運算符的相關用例中,往往會涉及到其他知識點,深拷貝和淺拷貝就是其中之一。即對象的淺拷貝會對主對象的值進行拷貝,而該值有可能是一個指針,指向內存中的同一個對象。,可以看到深拷貝和淺拷貝是對復制引用類型變量而言的。 在ES6的系列文章中,基本都會提到Spread——擴展運算符(...)。而在這個運算符的相關用例中,往往會涉及到其他知識點,深拷貝和淺拷貝就是其中之一。 背景知識 在討...
閱讀 1792·2023-04-25 15:51
閱讀 2501·2021-10-13 09:40
閱讀 2137·2021-09-23 11:22
閱讀 3247·2019-08-30 14:16
閱讀 2657·2019-08-26 13:35
閱讀 1852·2019-08-26 13:31
閱讀 880·2019-08-26 11:39
閱讀 2739·2019-08-26 10:33