Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
241 views
in Technique[技术] by (71.8m points)

javascript - Setting Array element changes all elements with same name

This is a follow-on post to the link below. I received help there that showed my code works as expected on jsfiddle, so there must be a concept I am not understanding when creating nested arrays and pushing objects to them: Updating elemint in JSON updates ALL

This question sounds like the exact issue, although in javascript for me, I am having but I cannot interpret how to apply the correct answer to my use case: How to avoid referencing the same index in an array (Java)?

This ordering UI is a little unorthodox where they select the accounts first, and then when they select any product after that, it has to be added to all accounts.

My Array is JS:

runningOrdfers = {
"id": 1402846607011,
"status": "unsaved",
"accounts": [
    {
        "compid": 919759,
        "compname": null,
        "products": [
            {
                "BCINUM": "539504",
                "ITEMUNIT": "EA",
                "ORDERDETAILS": [
                    {
                        "SHIPDATEID": "69230",
                        "SHIPPERIODID": "2096",
                        "QUANTITY": "1"
                    },
                    {
                        "SHIPDATEID": "69231",
                        "SHIPPERIODID": "2096",
                        "QUANTITY": "2"
                    }
                ],
                "SHIPPINGCOMMENTS": ""
            }
        ]
    },
    {
        "compid": 920001,
        "compname": null,
        "products": [
            {
                "BCINUM": "539504",
                "ITEMUNIT": "EA",
                "ORDERDETAILS": [
                    {
                        "SHIPDATEID": "69230",
                        "SHIPPERIODID": "2096",
                        "QUANTITY": "1"
                    },
                    {
                        "SHIPDATEID": "69231",
                        "SHIPPERIODID": "2096",
                        "QUANTITY": "2"
                    }
                ],
                "POTEXT": "",
                "SHIPPINGCOMMENTS": ""
            }
        ]
    }
]

Here is how I create and append objects to the array. First, create a new order:

var runningOrders = {};

function createNewOrder(event) {
    var uniqueID  = uniqueIdentifier();
    var accounts = [];
    var products = [];
    runningOrders.id = uniqueID;
    runningOrders.status = "unsaved";
    runningOrders["accounts"] = accounts;
    runningOrders.accounts["products"] = products;
    selectAccountsTab(event);
}

Then add the accounts to the order:

    function addAccountToOrder(compID) {
    getAccount(compID);
    var thisAccount = {};
    var n = savedAccountByCompID.length;
    for (var i = 0; i < n; i++) {
        var accountListObject  = savedAccountByCompID[i];
        thisAccount.compid = +accountListObject.COMPID;
        thisAccount.compname = +accountListObject.COMPNAME;
        thisAccount.products = [];
        runningOrders.accounts.push(thisAccount);
    }   
}

And finally add products to the accounts in the order just created:

    function setProductSelected(bcinum){
    var thisProductSelected = {};
    var thisProduct = "bcinum" + bcinum;
    var thisProductData = productData[thisProduct];

    thisProductSelected.BCINUM = thisProductData.BCINUM;
    thisProductSelected.ITEMUNIT = thisProductData.ITEMUNIT;
    thisProductSelected.ORDERDETAILS = [];

    thisOrderDetails = {
        SHIPDATEID: "69230",
        SHIPPERIODID: "2096",
        QUANTITY: ""
    };
    thisProductSelected.ORDERDETAILS.push(thisOrderDetails);

    thisOrderDetails = {
        SHIPDATEID: "69231",
        SHIPPERIODID: "2096",
        QUANTITY: ""
    };
    thisProductSelected.ORDERDETAILS.push(thisOrderDetails);

    var a = runningOrders.accounts.length;
    for (var ii = 0; ii < a; ii++) {
        currAccount = runningOrders.accounts[ii];    //possible problem? Loping over accounts and pushing same object?
        currAccount.products.push(thisProductSelected);
    }
}

My function to iterate and update the elements for the index I navigate to:

function updateComments(compID,bcinum,comment) {
    var accounts = runningOrders.accounts;
    var n = accounts.length;
    for (i = 0; i < n; i++) {
        if (accounts[i].compid == compID) {
            var p = accounts[i].products.length;
            for (ii = 0; ii < p; ii++) {
                if (accounts[i].products[ii].BCINUM == bcinum) {
                    accounts[i].products[ii].SHIPPINGCOMMENTS = comment;
                }   
            }       
        }
    }
}

When I call my update function, it is updating the SHIPPINGCOMMENTS at all index locations instead of just the one I wanted to be updated, which is based on compID:

updateComments(919759,539504,'sooner');

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Regardless of readbility issues this seems to work as designed as shown in this jsbin. It would seems there is something else going on.

This is a great example of how immutability can help a great deal. Designing your code around immutable data structures can alleviate complexity and confusion with where truth is. It is unfortunate that in JavaScript (by default) objects are managed by reference not by value so immutable objects are not directly supported by the language itself. Newer versions (ECMAScript 5) support the Object.freeze but you would need a polyfill in older / dysfunctional browsers.

To manage the complexity of a deeply nested data structure it could help to encapsulate the data in a custom objects (object as defined in classic object oriented design, although in the case of JavaScript this would be a prototypical object). However, this is beyond the scope of the original question (see this blog post on prototypical object oriented design).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...