0

I have a storage object that has an object datastore in it, like so:

data = {
    name1: 'value1',
    name2: 'value2',
    child: {
        name3: 'value3',
        name4: 'value4'
    }
}

What I need to do is pass the data variable, a name, and value, and have the object update, like so:

update(data, 'name1', 'foobar');

This works fine, but here's the catch: I need to be able to send a dot-notation name and have it update the proper child attribute. For instance:

update(data, 'child.name3', 'foobar');

Here is the code I'm using to do the traversal:

function update(data, fieldName, value) {
    var field = data
    var fieldNameParts = fieldName.split('.');
    while (fieldNameParts.length)
        field = field[fieldNameParts.shift()];
    field = (value === undefined) ? null : value;
}

So the problem is that "field" contains the new value, but "data.child.name3" does not. How do I traverse and update the main data object?

Any ideas on how to solve this?

1
  • have you considered using lodash.set? Commented Oct 24, 2020 at 12:55

2 Answers 2

1

You have iterated one step too far. Simply iterate one step backwards to get a reference to an object and then set the value of the property on that object:

function update(data, fieldName, value) {
    var field = data
    var fieldNameParts = fieldName.split('.');
    while (fieldNameParts.length > 1) // changed number of iterations
        field = field[fieldNameParts.shift()];
    field[fieldNameParts.shift()] = (value === undefined) ? null : value; // set value on property not on variable
}

What you were doing originally was:

var field = data.child.name3;
field = value;

What you want to be doing (and i do in the code above) is:

var field = data.child;
field.name3 = value;
Sign up to request clarification or add additional context in comments.

3 Comments

Nice work. I thought I tried that, but I guess I didn't do it correctly. This works, and is better than my solution since it avoids eval(). Thanks!
One small bug: I believe the last line should read field[fieldNameParts.shift()] and not just field[fieldNameParts]...
You are technically right. It still works, because the string representation of an array with 1 item (ensured by the while) is usually identical to the string representation of that 1 item. I updated my answer because it was not my intention to use such an obscure feature :), it was just a harmless bug.
0

Ok, I solved this using eval(). While this is a solution, I'm not sure it's the best one. Any additional thoughts?

function update(data, fieldName, value) {
    var evalStr = 'data';
    var fieldNameParts = fieldName.split('.');
    while (fieldNameParts.length)
        evalStr += '[\'' + fieldNameParts.shift() + '\']';
    evalStr += ' = (value === undefined) ? null : value;';
    eval(evalStr);
}

1 Comment

Interesting module, Robert. If I would have seen that previously, I may have used it instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.