1

我在我的应用程序中观察到(对我而言)无法解释的行为。我有一些通过 require() 包含的内容。其中一个名为“addUserFunction.js”,我有两个函数和一个包含对象的数组。
这是对象数组的定义:

exports.itemList = [{itemType:"info",itemName:"Information"},{...},{...}];

这是两个函数的定义:

exports.getItem = function(data) {
    var returnItem = {};
    for (var i=0;i<exports.itemList.length;i++) {
        if (exports.itemList[i].itemType == data.itemType){
            returnItem = exports.itemList[i]; // This line seems to pass a reference, not assign/copy
        }
    }
    returnItem.itemName = (data.itemName) ? data.itemName : returnItem.itemName;
    return returnItem;
}

exports.createPlan = function(formValues) {
    var returnItem = {
        id: 0,
        description: 'foobar',
        items: [
            exports.getItem({itemType:'info',itemName:'Information'}),
            exports.getItem({itemType:'somethingelse'}),
            exports.getItem({itemType:'bla',itemName:'yougottheidea'})
        ]
    };
    return returnItem;
}

现在的问题是:一旦我使用该函数exports.getItem并覆盖一些属性,getItem似乎将新创建returnItem的与原始的itemList[i]. 所以下一次调用itemList[i]使用第一次调用的属性值。希望解释清楚。怎么会这样?

createPlan()required()从另一个文件中调用,如下所示:

var aF = require('addUserFunctions');
function addUser() {
    var formValues = {name: 'test'};
    formValues.foo = aF.createPlan(formValues);
}
module.exports = addUser;
4

2 回答 2

1

每当您将变量或属性分配给对象(这包括各种对象,甚至数组)时,所分配的是对对象实例的引用的值。也就是说,如果我有

a = {};
b = a;

then a.foo = 1, then also b.foo === 1. But then if you do a = null;, b still points to the same object it was pointing to before. All you were doing in your code was digging through your array, finding an appropriate entry, an returning a reference to that entry. What you meant to do was to use that reference as a template for creating a new object. There are several ways to create such an object. The most common way is to use one of a common library's extend methods. However, if your object is more than one level deep, or your object is composed of thing other than trivial objects, things might get tricky, and it might not be possible using these generic methods to create a deep copy of your objects, only shallow ones.

The simplest approach is modify your getItem to clone your templates specifically copying into the new objects the properties you need. If any property in your template references some object that you may need a copy of, be sure to make a copy of that object as well.

于 2013-03-30T15:14:08.073 回答
0

原因是我不复制元素,我只链接到它,因为它是我要复制的对象。=不复制对象,只复制简单的变量类型,如数组、整数、布尔值等。

我创建了一个新函数,它知道这个对象的结构并逐个复制属性:

exports.copyListItem = function(item) {
    var newItem = {};
    newItem.itemType = item.itemType;
    newItem.itemName = item.itemName;
    // and so on
    return newItem;
}

不是最优雅的方式,但它有效。有关更通用的方法,请查看此处:克隆 JavaScript 对象的最优雅方法

我正在回答我自己的问题,因为最初的答案只是一个评论,并且(到目前为止)对我的反驳没有反应。

于 2013-03-30T14:45:34.460 回答