How to update/add element of the array in JavaScript?

Why not use an associate array for persons['data'], because .push() just uses index arrays

var persons = {
   data: {}
};

...
persons['data'][john.name] = john;
...

var updatedJohn = {name: 'John', age: 100};

// if statement isn't neccesary no more bc
// if the index is there it will override it and if not
// it will create a new index
persons['data'][updatedJohn.name] = updatedJohn;

The line didn't work for you because the person array was indexed by integers persons['data'].push() instead of strings persons['data'][stringIndex]


You can make a lookup table for every existing person if it's not in it, you push it in persons.data and create a new entry in the lookup table, else you rewrite full the person object without breaking the value's reference given. (I wrote a comment to explain this part).

JSFiddle here

var persons = {
    data: []
};

var bob = {name: 'Bob', age: 15};
var fill = {name: 'Fill', age: 20};
var mark = {name: 'Mark', age: 19};
var john = {name: 'John', age: 4};

persons['data'].push(bob);
persons['data'].push(fill);
persons['data'].push(mark);
persons['data'].push(john);

var personsHash = {};

// store an external reference for each persons
for (var i = 0, l = persons.data.length; i < l; i++) {
    personsHash[persons.data[i].name] = persons.data[i];
}

var updatedJohn = {name: 'John', age: 100};

if (!personsHash[updatedJohn.name]){
    personsHash[updatedJohn.name] = updatedJohn;
    persons['data'].push(updatedJohn);
} else {
    var key;
    var person = personsHash[updatedJohn.name];
    // comment if you don't want a full rewrite but just an update of attributes
    /**/
    for (key in person) {
        delete person[key];
    }
    /**/
    for (key in updatedJohn) {
        if (updatedJohn.hasOwnProperty(key)) {
            person[key] = updatedJohn[key];
        }
    }
}

Arrays in javascript are indexed by numbers (or at least should be).

persons['data'].push(bob);
persons['data'].push(fill);
persons['data'].push(mark);

Using persons[2] would give you {name: 'Mark', age: 19}.

While Javascript is so flexible that you can do as in @Sasa answer and use string indexes you may get kneecapped by other developers if you do since this is a VERY BAD PRACTICE.

[ADDED] Consider these examples of weird and unexpected behaviour:

var ary = [];
ary[0] = false;
ary['using string indexes in javascript arrays is stupid'] = true;
console.log('pop should return the last added element', ary.pop()); //  false - WTF?
console.log('lastIndexOf should be 1?', ary.lastIndexOf(true)); // -1 WTF?

Arrays in Javascript should be used as stacks. Think of a stack of cards, you either add (push) or take away cards (pull) but you don´t know which card is where (unless you´re cheating).

If you want a list of persons by name you would use an object to store persons:

persons.data = {};
persons['data']['Bob'] = bob;

Or alternatively you could filter the array to get values which match a predicate:

bob = persons.data.filter(function(person){
  return person["name"] === 'Bob';
})[0];

EDIT:

Example of a function that would create or find a person:

var persons = { data : [] }
persons.data.push({ name: 'Bob', age: 10 })

// returns the index of the newly added person
persons.addOrReplace = function(new_person, attr) {

    var attr = attr || 'name';
    var data = this.data;    
    for (var i = 0; i < data.length; i++) {
      if (data[i][attr] === new_person[attr]) {
        data[i] = new_person;
        return i;
      }
    }   
    return this.data.push(new_person);
}

persons.addOrReplace({ name: 'Bob', age: 11 });
console.log(persons.data.length); // 1
console.log(persons.data[0].age); // 11

persons.addOrReplace({ name: 'Joe', age: 11 });
console.log(persons.data.length); // 2
console.log(persons.data[persons.data.length -1].name); // Joe

You will need a query function like the following to help you find indices according to a property in your database: (JSFiddle)

function findIndexByProperty(data, key, value) {
    for (var i = 0; i < data.length; i++) {
        if (data[i][key] == value) {
            return i;
        }
    }
    return -1;
}

var johnIndex = findIndexByProperty(persons.data, 'name', 'John');
if (johnIndex > -1) {
    persons.data[johnIndex] = updatedJohn;
} else {
    persons.data.push(updatedJohn);
}

Note that this only returns the first record with name John. You will need to decide what you want it to do in the case of multiple such records - update all of them? This kind of problem is why databases usually have unique keys to identify records.

If using Underscore or lodash you already have a _.findIndex() function that can be used instead:

var johnIndex = _.findIndex(persons.data, { name: 'John' }); 

2021 update: Using modern JavaScript you can replace the function with

const johnIndex = persons.data.findIndex(p => p.name === "John")

Tags:

Javascript