David Coallier의 방법을 확장했습니다.
- 여러 객체를 병합 할 수있는 기능 추가
- 깊은 물체 지원
- 재정의 매개 변수 (마지막 매개 변수가 부울 인 경우 감지 됨)
override가 false이면 속성이 재정의되지 않지만 새 속성이 추가됩니다.
사용법 : obj.merge (merges ... [, override]);
내 코드는 다음과 같습니다.
Object.defineProperty(Object.prototype, "merge", {
enumerable: false,
value: function () {
var override = true,
dest = this,
len = arguments.length,
props, merge, i, from;
if (typeof(arguments[arguments.length - 1]) === "boolean") {
override = arguments[arguments.length - 1];
len = arguments.length - 1;
}
for (i = 0; i < len; i++) {
from = arguments[i];
if (from != null) {
Object.getOwnPropertyNames(from).forEach(function (name) {
var descriptor;
// nesting
if ((typeof(dest[name]) === "object" || typeof(dest[name]) === "undefined")
&& typeof(from[name]) === "object") {
// ensure proper types (Array rsp Object)
if (typeof(dest[name]) === "undefined") {
dest[name] = Array.isArray(from[name]) ? [] : {};
}
if (override) {
if (!Array.isArray(dest[name]) && Array.isArray(from[name])) {
dest[name] = [];
}
else if (Array.isArray(dest[name]) && !Array.isArray(from[name])) {
dest[name] = {};
}
}
dest[name].merge(from[name], override);
}
// flat properties
else if ((name in dest && override) || !(name in dest)) {
descriptor = Object.getOwnPropertyDescriptor(from, name);
if (descriptor.configurable) {
Object.defineProperty(dest, name, descriptor);
}
}
});
}
}
return this;
}
});
예 및 테스트 사례 :
function clone (obj) {
return JSON.parse(JSON.stringify(obj));
}
var obj = {
name : "trick",
value : "value"
};
var mergeObj = {
name : "truck",
value2 : "value2"
};
var mergeObj2 = {
name : "track",
value : "mergeObj2",
value2 : "value2-mergeObj2",
value3 : "value3"
};
assertTrue("Standard", clone(obj).merge(mergeObj).equals({
name : "truck",
value : "value",
value2 : "value2"
}));
assertTrue("Standard no Override", clone(obj).merge(mergeObj, false).equals({
name : "trick",
value : "value",
value2 : "value2"
}));
assertTrue("Multiple", clone(obj).merge(mergeObj, mergeObj2).equals({
name : "track",
value : "mergeObj2",
value2 : "value2-mergeObj2",
value3 : "value3"
}));
assertTrue("Multiple no Override", clone(obj).merge(mergeObj, mergeObj2, false).equals({
name : "trick",
value : "value",
value2 : "value2",
value3 : "value3"
}));
var deep = {
first : {
name : "trick",
val : "value"
},
second : {
foo : "bar"
}
};
var deepMerge = {
first : {
name : "track",
anotherVal : "wohoo"
},
second : {
foo : "baz",
bar : "bam"
},
v : "on first layer"
};
assertTrue("Deep merges", clone(deep).merge(deepMerge).equals({
first : {
name : "track",
val : "value",
anotherVal : "wohoo"
},
second : {
foo : "baz",
bar : "bam"
},
v : "on first layer"
}));
assertTrue("Deep merges no override", clone(deep).merge(deepMerge, false).equals({
first : {
name : "trick",
val : "value",
anotherVal : "wohoo"
},
second : {
foo : "bar",
bar : "bam"
},
v : "on first layer"
}));
var obj1 = {a: 1, b: "hello"};
obj1.merge({c: 3});
assertTrue(obj1.equals({a: 1, b: "hello", c: 3}));
obj1.merge({a: 2, b: "mom", d: "new property"}, false);
assertTrue(obj1.equals({a: 1, b: "hello", c: 3, d: "new property"}));
var obj2 = {};
obj2.merge({a: 1}, {b: 2}, {a: 3});
assertTrue(obj2.equals({a: 3, b: 2}));
var a = [];
var b = [1, [2, 3], 4];
a.merge(b);
assertEquals(1, a[0]);
assertEquals([2, 3], a[1]);
assertEquals(4, a[2]);
var o1 = {};
var o2 = {a: 1, b: {c: 2}};
var o3 = {d: 3};
o1.merge(o2, o3);
assertTrue(o1.equals({a: 1, b: {c: 2}, d: 3}));
o1.b.c = 99;
assertTrue(o2.equals({a: 1, b: {c: 2}}));
// checking types with arrays and objects
var bo;
a = [];
bo = [1, {0:2, 1:3}, 4];
b = [1, [2, 3], 4];
a.merge(b);
assertTrue("Array stays Array?", Array.isArray(a[1]));
a = [];
a.merge(bo);
assertTrue("Object stays Object?", !Array.isArray(a[1]));
a = [];
a.merge(b);
a.merge(bo);
assertTrue("Object overrides Array", !Array.isArray(a[1]));
a = [];
a.merge(b);
a.merge(bo, false);
assertTrue("Object does not override Array", Array.isArray(a[1]));
a = [];
a.merge(bo);
a.merge(b);
assertTrue("Array overrides Object", Array.isArray(a[1]));
a = [];
a.merge(bo);
a.merge(b, false);
assertTrue("Array does not override Object", !Array.isArray(a[1]));
내 equals 메소드는 여기에서 찾을 수 있습니다 : JavaScript의 객체 비교