JavaScriptは対象を深く理解する方法——Object.assign()
6009 ワード
Object.assign()
構文ターゲットオブジェクト. sourcesソースオブジェクト. 戻り値
ターゲット
説明
ターゲットオブジェクトの属性が同じキーである場合、属性はソースの属性によって覆われます.後のソースの属性は、前の属性を同様にカバーします.
エラーが発生した場合、例えば、属性が書き込み不可の場合、
例
オブジェクトをコピー
深度コピーには他の方法が必要です.Object.assign()コピーは属性値です.ソースオブジェクトの属性値がオブジェクトへの参照であれば、その参照値だけをコピーします.
Object.assign()
方法は、エニュメレート・属性のすべての値を1つまたは複数のソースオブジェクトから対象オブジェクトにコピーするために使用される.ターゲットオブジェクトに戻ります.構文
Object.assign(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 Clone
obj1 = { 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 Symbols
Object.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 } }
Polyfillif (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
});
}