javascript
JavaScript深入理解对象方法——Object.assign()
Object.assign()
Object.assign()方法用于將所有可枚舉屬性的值從一個或多個源對象復制到目標對象。它將返回目標對象。
語法
Object.assign(target, ...sources)
參數
- target
目標對象。 - sources
源對象。
返回值
目標對象。
描述
如果目標對象中的屬性具有相同的鍵,則屬性將被源中的屬性覆蓋。后來的源的屬性將類似地覆蓋早先的屬性。
Object.assign 方法只會拷貝源對象自身的并且可枚舉的屬性到目標對象。該方法使用源對象的[[Get]]和目標對象的[[Set]],所以它會調用相關 getter 和 setter。因此,它分配屬性,而不僅僅是復制或定義新的屬性。如果合并源包含getter,這可能使其不適合將新屬性合并到原型中。為了將屬性定義(包括其可枚舉性)復制到原型,應使用Object.getOwnPropertyDescriptor()和Object.defineProperty() 。
String類型和 Symbol 類型的屬性都會被拷貝。
在出現錯誤的情況下,例如,如果屬性不可寫,會引發TypeError,如果在引發錯誤之前添加了任何屬性,則可以更改target對象。
注意,Object.assign 會跳過那些值為 null 或 undefined 的源對象。
示例
復制一個對象
var obj = { a: 1 }; var copy = Object.assign({}, obj); console.log(copy); // { a: 1 }深拷貝問題
針對深拷貝,需要使用其他方法,因為 Object.assign()拷貝的是屬性值。假如源對象的屬性值是一個指向對象的引用,它也只拷貝那個引用值。
function test() {'use strict';let obj1 = { a: 0 , b: { c: 0}};let obj2 = Object.assign({}, obj1);console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}obj1.a = 1;console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}obj2.a = 2;console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}}obj2.b.c = 3;console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}}// Deep Cloneobj1 = { a: 0 , b: { c: 0}};let obj3 = JSON.parse(JSON.stringify(obj1));obj1.a = 4;obj1.b.c = 4;console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}} }test();合并對象
var o1 = { a: 1 }; var o2 = { b: 2 }; var o3 = { c: 3 };var obj = Object.assign(o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 } console.log(o1); // { a: 1, b: 2, c: 3 }, 注意目標對象自身也會改變。合并具有相同屬性的對象
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 }屬性被后續參數中具有相同屬性的其他對象覆蓋。
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)]繼承屬性和不可枚舉屬性是不能拷貝的
var obj = Object.create({foo: 1}, { // foo 是個繼承屬性。bar: {value: 2 // bar 是個不可枚舉屬性。},baz: {value: 3,enumerable: true // baz 是個自身可枚舉屬性。} });var copy = Object.assign({}, obj); console.log(copy); // { baz: 3 }原始類型會被包裝為對象
var v1 = "abc"; var v2 = true; var v3 = 10; var v4 = Symbol("foo")var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); // 原始類型會被包裝,null 和 undefined 會被忽略。 // 注意,只有字符串的包裝對象才可能有自身可枚舉屬性。 console.log(obj); // { "0": "a", "1": "b", "2": "c" }異常會打斷后續拷貝任務
var target = Object.defineProperty({}, "foo", {value: 1,writable: false }); // target 的 foo 屬性是個只讀屬性。Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4}); // TypeError: "foo" is read-only // 注意這個異常是在拷貝第二個源對象的第二個屬性時發生的。console.log(target.bar); // 2,說明第一個源對象拷貝成功了。 console.log(target.foo2); // 3,說明第二個源對象的第一個屬性也拷貝成功了。 console.log(target.foo); // 1,只讀屬性不能被覆蓋,所以第二個源對象的第二個屬性拷貝失敗了。 console.log(target.foo3); // undefined,異常之后 assign 方法就退出了,第三個屬性是不會被拷貝到的。 console.log(target.baz); // undefined,第三個源對象更是不會被拷貝到的。拷貝訪問器
var obj = {foo: 1,get bar() {return 2;} };var copy = Object.assign({}, obj); // { foo: 1, bar: 2 } // copy.bar的值來自obj.bar的getter函數的返回值 console.log(copy); // 下面這個函數會拷貝所有自有屬性的屬性描述符 function completeAssign(target, ...sources) {sources.forEach(source => {let descriptors = Object.keys(source).reduce((descriptors, key) => {descriptors[key] = Object.getOwnPropertyDescriptor(source, key);return descriptors;}, {});// Object.assign 默認也會拷貝可枚舉的SymbolsObject.getOwnPropertySymbols(source).forEach(sym => {let descriptor = Object.getOwnPropertyDescriptor(source, sym);if (descriptor.enumerable) {descriptors[sym] = descriptor;}});Object.defineProperties(target, descriptors);});return target; }var copy = completeAssign({}, obj); console.log(copy); // { foo:1, get bar() { return 2 } }Polyfill
if (typeof Object.assign != 'function') {// Must be writable: true, enumerable: false, configurable: trueObject.defineProperty(Object, "assign", {value: function assign(target, varArgs) { // .length of function is 2'use strict';if (target == null) { // TypeError if undefined or nullthrow 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 nullfor (var nextKey in nextSource) {// Avoid bugs when hasOwnProperty is shadowedif (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {to[nextKey] = nextSource[nextKey];}}}}return to;},writable: true,configurable: true}); }總結
以上是生活随笔為你收集整理的JavaScript深入理解对象方法——Object.assign()的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ElasticSearch _xpack
- 下一篇: vscode使用-添加格式化插件