将一个对象包含在另一个对象中
include an object inside another
project = {id: 1}
milestone = { id: 1, name: "milestone a" }
tasks = [{ name: 'task a' }, { name: 'task b' }]
我需要从上面的三个对象创建一个对象,如下所示:
project = { id:1, milestone: {id: 1, name: "milestone a", tasks: [...]} }
我尝试了项目里程碑=里程碑,...但是如果我有很多变量和赋值,就不可能使用。
所以我的问题是,如何将一个对象包含在另一个对象中并修改父对象,以便:
a = {id: 1}
b = {id: 2}
a.magic_method(b) // => {id: 1, b: {id: 2}}
$.extend
:
$.extend(project, {milestone: milestone}, {tasks: tasks});
下面是一个示例:http://jsfiddle.net/hDWef/
编辑:
哦,我刚刚意识到,您希望将tasks
合并到milestone
中,milestone
合并到项目中。
在这种情况下,您必须合并合并的对象。
但是从一开始就像这样设置对象结构会更容易,就像@Amberlamps和Van Ootegem建议的那样@Elias。
我更新了答案
编辑2: 将类型检查更改为使用 instanceof
,因为{}.toString.call(o)
返回对象 ClassName,它可以是 nodeElement 的任何内容,window
返回"[object global]"
您可以编写一个合并函数
,该函数将多个对象的属性合并为一个。
var merge = (function () {
var initThis = this;
return function () {
var len = arguments.length - 1,
srt, tmp;
if ("function" === typeof arguments[arguments.length - 1]) srt = arguments[arguments.length - 1];
else {
srt = function (a, b, prop) {
if (!prop) return a;
return a[prop];
};
len++;
}
var merge = this === initThis ? {} : this;
for (var i = 0; i < len; i++) inner(arguments[i], merge);
function inner(obj2, obj1) {
if (obj2 instanceof Array) {
if (!obj1) obj1 = [];
if (typeof obj1 != "object") obj1 = (tmp = srt(obj1, obj2, null), tmp) === obj2 ? [] : tmp;
for (var i = 0; i < obj2.length; i++) if (!obj1[i] && typeof obj2[i] == "object") obj1[i] = inner(obj2[i]);
else if (obj1[i] && typeof obj2[i] == "object") obj1[i] = inner(obj2[i], obj1[i]);
else if (obj1[i]) obj1[i] = srt(obj1, obj2, i) || obj1[i];
else obj1[i] = obj2[i];
} else if (obj2 instanceof Object) {
if (!obj1) obj1 = {};
if (typeof obj1 != "object") obj1 = (tmp = srt(obj1, obj2, null), tmp) === obj2 ? {} : tmp; //If obj2 is returned, set to empty obj to allow deep cloning
for (var prop in obj2) {
var isObj = "object" === typeof obj2[prop];
if (!obj1[prop] && isObj) obj1[prop] = inner(obj2[prop]);
else if (obj1[prop] && isObj) obj1[prop] = inner(obj2[prop], obj1[prop]);
else if (obj1[prop]) obj1[prop] = srt(obj1, obj2, prop) || obj1[prop];
else obj1[prop] = obj2[prop];
}
} else {
throw new SyntaxError ("expected " + obj2 + " to be of type object");
}
return obj1;
}
return merge;
};
})();
合并函数接受 n 个参数,其中最后一个可以是消除歧义函数,当当前合并对象的 2 个属性相同时,将调用该函数。
此消除歧义函数使用 3 个参数调用:
-
a
- 属性合并的当前第一个对象。
-
b
- 属性合并的当前第二个对象。
-
prop
- 合并的属性的名称
函数的返回值将分配给当前合并属性。
例如,如果存在冲突,return a[prop]
将始终分配第一个对象的值。
如果没有函数作为最后一个参数传递,则默认行为为:保留第一个 Object 的值。
现在我们必须在 milestone
和 tasks
上调用 merge
,然后使用合并的 milestone
对象进行merge
project
,如下所示。
project = {id: 1};
milestone = { id: 1, name: "milestone a" };
tasks = [{ name: 'task a' }, { name: 'task b' }];
var merged = merge (project,{milestone: merge (milestone , {tasks:tasks} )});
//^^^ mergeception
//^^^ Wrap it because you want the complete 'tasks' object, not merge the properties this time.
console.log (JSON.stringify(merged));
/* {
"id": 1,
"milestone": { //<- milestone in merged/project
"id": 1,
"name": "milestone a",
"tasks": [{ //<- tasks in milestone
"name": "task a"
}, {
"name": "task b"
}]
}
} */
您可以看到它返回一个合并的对象。
这是JSBin上的演示
或者如果你想要jQuery的方式。
var merged = $.extend(project, {milestone : $.extend (milestone, {tasks:tasks}) });
使用这个
$.extend(project, {milestone: $.extend(milestone,{tasks:tasks})});
没有办法知道变量的人类可读名称是什么。因此,您将找不到满足您要求的神奇功能。
此外,你永远不需要这样的函数,因为你决定你的变量是什么样的。因此,与其寻找神奇的函数,不如将变量名称编写为对象属性:
var a = { id: "idA" };
var b = { id: "idB" };
a.b = b;
// it does not get more simple than that!
这应该可以实现您所追求的。我将其创建为一个函数,以便您可以重用它。
这个想法:
function (parent, {object list of children to combine to parent});
资料来源:
var project = {id: 1};
var milestone = { id: 1, name: "milestone a" };
var tasks = [{ name: 'task a' }, { name: 'task b' }];
var finalList;
function combine(parent, combineList) {
var len = combineList.length;
var returnList = {}
// Add values from the parent, in our case 'project'
for (prop in parent) {
returnList[prop] = parent[prop];
}
// Add in children
for (obj in combineList) {
returnList[obj] = combineList[obj];
}
return returnList;
}
finalList = combine(
project, {
'milestone': milestone,
'tasks': tasks
});
console.log(finalList);
// finalList = {"id":1,"milestone":{"id":1,"name":"milestone a"},"tasks":[{"name":"task a"},{"name":"task b"}]}
- 对一个对象使用reduce可以返回一个没有't在数组中包含目标字母
- 预期响应包含一个对象,但在angular js中得到一个数组错误
- 响应应包含一个对象,但得到的却是GET操作的数组
- 替换对象's属性,其中包含JavaScript中另一个对象的属性,不包含库
- Rails JavaScript 包含 TypeError:“null”不是一个对象(评估 'document.
- 如何创建一个只包含时间而不包含日期的即时对象
- 将一个对象包含在另一个对象中
- 我如何通过另一个对象访问一个对象,这个对象包含一个对象,这个对象是我想要访问的对象的属性
- 如何切换映射-发出一个对象包含原始和新的可观察对象
- 如何判断一个对象是否包含一个数组
- 检查Javascript对象是否包含与另一个对象相同的键/值对
- 在JS中如何检查对象数组是否包含一个对象
- 将JSON发送到WebAPI - JSON对象包含一个图像(字节)-得到错误:表达式太长或太复杂而无法编译
- 资源配置错误.预期响应包含一个对象,但得到一个数组
- Angular-UI模态错误:期望的响应包含一个对象,但得到一个数组
- AngularJS -期望的响应包含一个对象,但得到的却是一个数组
- 对象的Javascript数组,其中一个对象还包含一个数组
- jquery或javascript如何查找数组是否包含一个对象,以及该对象是否具有指定值的名称
- 对象比较:检查一个对象是否包含整个其他对象
- 将只包含更改的对象应用到javascript中的另一个对象