变量被意外覆盖

时间:2013-03-29 21:48:12

标签: javascript variables module appcelerator commonjs

我在我的应用程序中观察(对我来说)不可解释的行为。 我有几个包括via require()。在其中一个名为“addUserFunction.js”中,我有两个函数和一个包含对象的数组 这是objects-array的定义:

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;

2 个答案:

答案 0 :(得分:1)

无论何时为对象(包括所有类型的对象,甚至是数组)分配变量或属性,分配的内容都是对象实例的引用值。也就是说,如果我有

a = {};
b = a;

然后是a.foo = 1,然后是b.foo === 1。但是如果你做a = null;,b仍然指向它之前指向的同一个对象。您在代码中所做的只是挖掘数组,找到合适的条目,返回对该条目的引用。你打算做的是使用该引用作为创建新对象的模板。有几种方法可以创建这样的对象。最常见的方法是使用公共库的extend方法之一。但是,如果您的对象深度超过一级,或者您的对象由除了普通对象之外的其他对象组成,则事情可能会变得棘手,并且可能无法使用这些通用方法创建对象的深层副本,只有浅层的。

最简单的方法是修改您的getItem以克隆您的模板,特别是将您需要的属性复制到新对象中。如果模板中的任何属性引用了某些可能需要副本的对象,请务必复制该对象。

答案 1 :(得分:0)

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

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

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

不是最优雅的方式,但它的工作原理。有关更一般的方法,请查看此处:Most elegant way to clone a JavaScript Object

我正在回答我自己的问题,因为原来的回答只是一个评论,对我的反评论没有反应(到目前为止)。