在我的视图中,我想创建一个要返回的新对象,而不是传递给我的map函数的对象。我想做一些验证并向新对象添加一些字段。我对视图的map函数看起来像这样(没有reduce):
function(doc) {
if(doc.type == "mytype") {
var newobj = null;
if( doc.someObjField ) {
newobj = doc.someObjField; //LINE 5: want a copy but get a reference
}
else {
newobj = new Object(); //field didn't exist create a new object
}
newobj.superId = doc._id; //these fields get added to the DB
newobj.superName = doc.name;
newobj.newField = doc.field;
emit(doc._id, newobj);
}
}
问题是,当此视图运行时,它最终会向数据库中的文档添加一些新字段。在Futon中编辑文档时我看不到字段,但它们出现在文档的每个视图中。
我认为这是因为LINE 5创建了对文档该字段的引用而不是副本。这是否意味着我必须在我的所有视图中包含clone()函数才能获得我想要的内容?也许我在考虑这个错误?
更新:我使用的是CouchDB 1.0.0版并升级到1.0.1版,似乎行为已经改变。在以前的版本中,在一个视图中修改了“doc”时,修改出现在所有视图中。在最新版本中,情况似乎并非如此。
答案 0 :(得分:3)
newobj = doc.someObjField
确实提供了引用而不是副本,因此您将不得不迭代doc.someObjField
的属性并将它们复制到新对象。
这不是那么简单,以下显示了如何制作浅层克隆的示例:
// get the class of an object, this is a lot better than messing with typeof and instanceof
function is(type, obj) {
return Object.prototype.toString.call(obj).slice(8, -1) === type;
}
function copy(val) {
if (is('Object', val)) { // shallow clone objects
var obj = {};
for (var f in val) {
if (val.hasOwnProperty(f)) {
obj[f] = val[f];
}
}
return obj;
} else {
return is('Array', val) ? val.slice() : val; // shallow clone arrays
}
}
您的代码如下所示:
newobj = doc.someObjField ? copy(doc.someObjField) : {};
现在,如果someObjField
将对象或数组作为其属性,那么它们将只是引用,因此您必须以递归方式克隆它们。