1

アプリで (私にとっては) 説明のつかない動作が見られます。require() を介していくつかのインクルードがあります。そのうちの 1 つである「addUserFunction.js」には、2 つの関数とオブジェクトを含む配列があります。
オブジェクト配列の定義は次のとおりです。

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

これは、2 つの関数の定義です。

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;

それではa.foo = 1、またb.foo === 1。しかし、そうするとa = null;、 b は以前に指していたのと同じオブジェクトを指し続けます。コードで行っていたのは、配列を掘り下げて適切なエントリを見つけ、そのエントリへの参照を返すことだけでした。あなたが意図したのは、その参照を新しいオブジェクトを作成するためのテンプレートとして使用することでした。このようなオブジェクトを作成するには、いくつかの方法があります。最も一般的な方法は、共通ライブラリのextendメソッドの 1 つを使用することです。ただし、オブジェクトが 1 レベル以上の深さである場合、またはオブジェクトが自明なオブジェクト以外のもので構成されている場合は、扱いが難しくなる可能性があり、これらの汎用メソッドを使用してオブジェクトの深いコピーを作成することはできず、浅いコピーのみを作成できます。もの。

最も簡単な方法はgetItem、テンプレートを複製して必要なプロパティを新しいオブジェクトに具体的にコピーするように変更することです。テンプレート内のいずれかのプロパティが、コピーが必要なオブジェクトを参照している場合は、そのオブジェクトのコピーも必ず作成してください。

于 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 に答える