1941

Here is my object literal:

var obj = {key1: value1, key2: value2};

How can I add field key3 with value3 to the object?

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
James Skidmore
  • 49,340
  • 32
  • 108
  • 136
  • 5
    Well, the whole issue of associative arrays in JS is weird, because you can do this... http://dreaminginjavascript.wordpress.com/2008/06/27/how-weird-are-javascript-arrays/ – Nosredna Jul 22 '09 at 23:48
  • 2
    @Nosredna - the point is, there are no such things as associative arrays in javascript. In that article he is adding object properties to an array object, but these are not really part of the 'array'. – UpTheCreek Aug 30 '12 at 09:34
  • 2
    Is there a way to conditionally set key:value pairs in an object literal with future ES+ implementations? – Con Antonakos Apr 01 '16 at 19:00

17 Answers17

2987

There are two ways to add new properties to an object:

var obj = {
    key1: value1,
    key2: value2
};

Using dot notation:

obj.key3 = "value3";

Using square bracket notation:

obj["key3"] = "value3";

The first form is used when you know the name of the property. The second form is used when the name of the property is dynamically determined. Like in this example:

var getProperty = function (propertyName) {
    return obj[propertyName];
};

getProperty("key1");
getProperty("key2");
getProperty("key3");

A real JavaScript array can be constructed using either:

The Array literal notation:

var arr = [];

The Array constructor notation:

var arr = new Array();
pimvdb
  • 151,816
  • 78
  • 307
  • 352
Ionuț G. Stan
  • 176,118
  • 18
  • 189
  • 202
  • Yes Nosredna, you're right. I corrected after your comment on seth's answer. I know the implications, it was just the inertia of my mind :) – Ionuț G. Stan Jul 22 '09 at 23:33
  • 4
    obj is an object. The part between (and including) the braces is the object literal. obj is not an object literal. – Nosredna Jul 22 '09 at 23:34
  • ...although it is recommended (also by JSLint) to use the first Array constructor notation... Just so we're clear about that... – Robert Koritnik Aug 29 '12 at 13:36
  • 44
    what if the key is a number? obj.123 = 456 doesn't work. obj[123] = 456 does work though – axel wolf Nov 02 '12 at 10:39
  • 21
    @axelfreudiger indeed, anything that's not syntactically a valid variable identifier has to be used with bracket notation. – Ionuț G. Stan Nov 02 '12 at 10:42
  • Using obj['newvalue'] = 'blah; does not append it to the end as far as i can see. It is adding it at the beginning – Metropolis Mar 25 '14 at 18:51
  • @Ionuț G. Stan Could the answer be improved by saying you can set the key of the object literal dynamically such as in the following for loop: `for (var pIdx = 0; pIdx < products.length; pIdx ++) { var id = products[pIdx].id; productById[id] = products[pIdx]; }` – Kent Bull Apr 07 '14 at 06:31
  • If the bracket notation is used, I'm guessing the key is stored as a string? What happens if the dot notation is used -- would the key be stored as string as well? – ayjay Jun 13 '14 at 18:44
  • 1
    Probably not too important (especially overkill for such a simple question), but it might be good to include the ability to add a property with `Object.defineProperty`, since it's supported quite well in modern browsers – Ian Jul 29 '14 at 00:27
  • **Can I sort by values? for ex I want to iterate keys starting from the key that has the smallest value** – Khalil Khalaf Jun 08 '17 at 21:24
  • 1
    @KyleKhalaf `Object.keys({"b": 1, "c": 3, "a": 2}).sort().forEach(console.log);` – Ionuț G. Stan Jun 09 '17 at 06:50
  • Awesome! what if the value is an array of items, and I want to start with the key that has the smallest array? – Khalil Khalaf Jun 09 '17 at 15:53
  • @KyleKhalaf Take a look at `Array.sort`, you can give it a custom compare function: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/sort?v=control – Ionuț G. Stan Jun 09 '17 at 16:05
  • Did ya know that if you create an array with dynamic key/value pairs that it's length property will be zero? To solve this, one could simply overwrite the length property of the array they're creating. Setting var myarray["length"] = numArrayFields solved this issue for me. Assuming you are keeping track of the number of fields your're adding to your array somehow. – Giga Chad Coding Apr 17 '18 at 05:33
  • 2
    @JohnSmith the `length` property isn't set because it's not an array, it's an object/map/dictionary. – Ionuț G. Stan Apr 17 '18 at 06:09
  • using dot notation doesn't allows you to add the value in var as key of the object – Piyush May 11 '20 at 09:27
  • Was there a way to use Key => Value Syntax or Am i getting confused with php. Sure i saw a Js Css implementation where they used arrow to point to the values... – Ryan Stone Oct 13 '20 at 06:17
  • @RyanStone I think you saw a function expression: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions – Ionuț G. Stan Oct 13 '20 at 15:15
  • How do you insert key-value pair at a particular index? Or are JS objects unordered like Python dictionaries? – mLstudent33 Nov 13 '20 at 22:45
  • Can we also use .push() for inserting pairs? – deep206 Feb 08 '21 at 15:32
  • @IonuțG.Stan do you know that this answer is dated. The statement "There are two ways to add new properties to an object" is wrong as of 2023. In addition to what you have mentioned here are Object.assign, spread syntax,Object.defineProperty. – Ahmad Ismail May 23 '23 at 10:59
  • @AhmadIsmail yes, but fortunately other answers already cover that. Feel free to edit the answer with additional info or down vote it if it's wrong. Unfortunately, I don't have the time, nor the incentive, to keep my old SO answers up to date. – Ionuț G. Stan May 23 '23 at 17:35
659

Year 2017 answer: Object.assign()

Object.assign(dest, src1, src2, ...) merges objects.

It overwrites dest with properties and values of (however many) source objects, then returns dest.

The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.

Live example

var obj = {key1: "value1", key2: "value2"};
Object.assign(obj, {key3: "value3"});

document.body.innerHTML = JSON.stringify(obj);

Year 2018 answer: object spread operator {...}

obj = {...obj, ...pair, scalar};

From MDN:

It copies own enumerable properties from a provided object onto a new object.

Shallow-cloning (excluding prototype) or merging of objects is now possible using a shorter syntax than Object.assign().

Note that Object.assign() triggers setters whereas spread syntax doesn’t.

Live example

It works in current Chrome and current Firefox. They say it doesn’t work in current Edge.

var obj = {key1: "value1", key2: "value2"};
var pair = {key3: "value3"};
var scalar = "value4"
obj = {...obj, ...pair, scalar};

document.body.innerHTML = JSON.stringify(obj);

Year 2019 answer

Object assignment operator +=:

obj += {key3: "value3"};

Oops... I got carried away. Smuggling information from the future is illegal. Duly obscured!

Abdull
  • 26,371
  • 26
  • 130
  • 172
7vujy0f0hy
  • 8,741
  • 1
  • 28
  • 33
111

I have grown fond of the LoDash / Underscore when writing larger projects.

Adding by obj['key'] or obj.key are all solid pure JavaScript answers. However both of LoDash and Underscore libraries do provide many additional convenient functions when working with Objects and Arrays in general.

.push() is for Arrays, not for objects.

Depending what you are looking for, there are two specific functions that may be nice to utilize and give functionality similar to the the feel of arr.push(). For more info check the docs, they have some great examples there.

_.merge (Lodash only)

The second object will overwrite or add to the base object. undefined values are not copied.

var obj = {key1: "value1", key2: "value2"};
var obj2 = {key2:"value4", key3: "value3", key4: undefined};
_.merge(obj, obj2);
console.log(obj);
// → {key1: "value1", key2: "value4", key3: "value3"} 

_.extend / _.assign

The second object will overwrite or add to the base object. undefined will be copied.

var obj = {key1: "value1", key2: "value2"};
var obj2 = {key2:"value4", key3: "value3", key4: undefined};
_.extend(obj, obj2);
console.log(obj);
// → {key1: "value1", key2: "value4", key3: "value3", key4: undefined}

_.defaults

The second object contains defaults that will be added to base object if they don't exist. undefined values will be copied if key already exists.

var obj = {key3: "value3", key5: "value5"};
var obj2 = {key1: "value1", key2:"value2", key3: "valueDefault", key4: "valueDefault", key5: undefined};
_.defaults(obj, obj2);
console.log(obj);
// → {key3: "value3", key5: "value5", key1: "value1", key2: "value2", key4: "valueDefault"}

$.extend

In addition, it may be worthwhile mentioning jQuery.extend, it functions similar to _.merge and may be a better option if you already are using jQuery.

The second object will overwrite or add to the base object. undefined values are not copied.

var obj = {key1: "value1", key2: "value2"};
var obj2 = {key2:"value4", key3: "value3", key4: undefined};
$.extend(obj, obj2); 
console.log(obj);
// → {key1: "value1", key2: "value4", key3: "value3"}

Object.assign()

It may be worth mentioning the ES6/ ES2015 Object.assign, it functions similar to _.merge and may be the best option if you already are using an ES6/ES2015 polyfill like Babel if you want to polyfill yourself.

The second object will overwrite or add to the base object. undefined will be copied.

var obj = {key1: "value1", key2: "value2"};
var obj2 = {key2:"value4", key3: "value3", key4: undefined};
Object.assign(obj, obj2); 
console.log(obj);
// → {key1: "value1", key2: "value4", key3: "value3", key4: undefined}
Sir.Nathan Stassen
  • 1,843
  • 4
  • 21
  • 25
88

You could use either of these (provided key3 is the acutal key you want to use)

arr[ 'key3' ] = value3;

or

arr.key3 = value3;

If key3 is a variable, then you should do:

var key3 = 'a_key';
var value3 = 3;
arr[ key3 ] = value3;

After this, requesting arr.a_key would return the value of value3, a literal 3.

ACK_stoverflow
  • 3,148
  • 4
  • 24
  • 32
seth
  • 36,759
  • 7
  • 60
  • 57
  • 9
    This is not an array but an object. JS arrays are indexed only by integer. Try to do arr.length and it'll return 0. More reading about this: http://www.less-broken.com/blog/2010/12/lightweight-javascript-dictionaries.html – DevAntoine Jul 18 '12 at 12:27
  • 1
    @DevAntoine's link is not accessible. If you want to get the "length" of this array type, use: Object.keys(your_array).length More reading about this problem, see: https://stackoverflow.com/questions/21356880/array-length-returns-0 – The Anh Nguyen Mar 14 '18 at 05:01
  • 1
    One could also simple overwrite the length property of the array they're creating. Setting var myarray["length"] = numArrayFields solve this issue for me. Assuming you are keeping track of the number of fields your're adding to your array somehow that is. – Giga Chad Coding Apr 17 '18 at 05:31
74

Performance

Today 2020.01.14 I perform tests on MacOs HighSierra 10.13.6 on Chrome v78.0.0, Safari v13.0.4 and Firefox v71.0.0, for chosen solutions. I divide solutions to mutable (first letter M) and immutable (first letter I). I also provide few immutable solutions (IB,IC,ID/IE) not yet published in answers to this question

Conclusions

  • fastest mutable solutions are much faster than fastest immutable (>10x)
  • classic mutable approach like obj.key3 = "abc" (MA,MB) is fastest
  • for immutable solutions the {...obj, key3:'abc'} and Object.assign (IA,IB) are fastest
  • surprisingly there are immutable solutions faster than some mutable solutions for chrome (MC-IA) and safari (MD-IB)

enter image description here

Details

In snippet below there are presended tested solution, you can prefrom test on your machine HERE (update 2022: I send Big thanks to Josh DeLong who rewrite tests from jspref.com which stops working to jsbench.me)

var o = {
    key1: true,
    key2: 3,
};

var log= (s,f)=> console.log(`${s} --> ${JSON.stringify(f({...o}))}`);



function MA(obj) {
  obj.key3 = "abc";
  return obj;
}

function MB(obj) {
  obj['key3'] = "abc";
  return obj;
}

function MC(obj) {
  Object.assign(obj, {key3:'abc'});
  return obj;
}

function MD(obj) {
  Object.defineProperty(obj, 'key3', {
    value: "abc",       // undefined by default
    enumerable: true,      // false by default
    configurable: true,    // false by default
    writable: true         // false by default
  });
  return obj;
}

function IA(obj) {
  return {...obj, key3:'abc'};
}

function IB(obj) {
  return Object.assign({key3:'abc'}, obj);
}

function IC(obj) {
  let ob= JSON.parse(JSON.stringify(obj))
  ob.key3 = 'abc';
  return ob;
}


function ID(obj) {
    let ob= Object.fromEntries(Object.entries(obj));
  ob.key3 = 'abc';
  return ob;
}

function IE(obj) {
    return Object.fromEntries(Object.entries(obj).concat([['key3','abc']]))
}



log('MA',MA);
log('MB',MB);
log('MC',MC);
log('MD',MD);
log('IA',IA);
log('IB',IB);
log('IC',IC);
log('ID',ID);
log('IE',IE);
This snippet only presents code - it not perform tests itself!

enter image description here

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
34

The spread operator is a useful and quick syntax for adding items to arrays, combining arrays or objects, and spreading an array out into a function’s arguments. Now, ES2018 comes with spread properties to object literals. It copies its own enumerable properties from a provided object onto a new object.

The spread syntax is useful for combining the properties and methods on objects into a new object:

You can add property in an object like this

const obj1 = {hello: ""};
const obj2 = {...obj1, laugh: "" };
console.log('obj1', obj1)
console.log('obj2', obj2)

You can also combine objects like this

const objectOne = {hello: ""}
const objectTwo = {world: ""}
const objectThree = {...objectOne, ...objectTwo, laugh: ""}
console.log(objectThree) // Object { hello: "", world: "", laugh: "" }
const objectFour = {...objectOne, ...objectTwo, laugh: () => {console.log("".repeat(5))}}
objectFour.laugh() // 
Subham Goyal
  • 806
  • 9
  • 9
32
arr.key3 = value3;

because your arr is not really an array... It's a prototype object. The real array would be:

var arr = [{key1: value1}, {key2: value2}];

but it's still not right. It should actually be:

var arr = [{key: key1, value: value1}, {key: key2, value: value2}];
Robert Koritnik
  • 103,639
  • 52
  • 277
  • 404
17

Simply adding properties:

And we want to add prop2 : 2 to this object, these are the most convenient options:

  1. Dot operator: object.prop2 = 2;
  2. square brackets: object['prop2'] = 2;

So which one do we use then?

The dot operator is more clean syntax and should be used as a default (imo). However, the dot operator is not capable of adding dynamic keys to an object, which can be very useful in some cases. Here is an example:

const obj = {
  prop1: 1
}

const key = Math.random() > 0.5 ? 'key1' : 'key2';

obj[key] = 'this value has a dynamic key';

console.log(obj);

Merging objects:

When we want to merge the properties of 2 objects these are the most convenient options:

  1. Object.assign(), takes a target object as an argument, and one or more source objects and will merge them together. For example:

const object1 = {
  a: 1,
  b: 2,
};

const object2 = Object.assign({
  c: 3,
  d: 4
}, object1);

console.log(object2);
  1. Object spread operator ...

const obj = {
  prop1: 1,
  prop2: 2
}

const newObj = {
  ...obj,
  prop3: 3,
  prop4: 4
}

console.log(newObj);

Which one do we use?

  • The spread syntax is less verbose and has should be used as a default imo. Don't forgot to transpile this syntax to syntax which is supported by all browsers because it is relatively new.
  • Object.assign() is more dynamic because we have access to all objects which are passed in as arguments and can manipulate them before they get assigned to the new Object.
Willem van der Veen
  • 33,665
  • 16
  • 190
  • 155
14

I know there is already an accepted answer for this but I thought I'd document my idea somewhere. Please [people] feel free to poke holes in this idea, as I'm not sure if it is the best solution... but I just put this together a few minutes ago:

Object.prototype.push = function( key, value ){
   this[ key ] = value;
   return this;
}

You would utilize it in this way:

var obj = {key1: value1, key2: value2};
obj.push( "key3", "value3" );

Since, the prototype function is returning this you can continue to chain .push's to the end of your obj variable: obj.push(...).push(...).push(...);

Another feature is that you can pass an array or another object as the value in the push function arguments. See my fiddle for a working example: http://jsfiddle.net/7tEme/

sadmicrowave
  • 39,964
  • 34
  • 108
  • 180
  • 1
    maybe this isn't a good solution, I seem to be getting errors in jquery1.9: `TypeError: 'undefined' is not a function (evaluating 'U[a].exec(s)')` which is weird because it works in jsfiddle even with jquery1.9 – sadmicrowave Jun 26 '13 at 18:43
  • 5
    You should not extend Object.prototype; this breaks the "object-as-hashtables" feature of JavaScript (and subsequently a lot of libraries such as the Google Maps JS API). See discussion: http://stackoverflow.com/questions/1827458/prototyping-object-in-javascript-breaks-jquery – Justin R. Oct 03 '13 at 16:54
12

Two most used ways already mentioned in most answers

obj.key3 = "value3";

obj["key3"] = "value3";

One more way to define a property is using Object.defineProperty()

Object.defineProperty(obj, 'key3', {
  value: "value3",       // undefined by default
  enumerable: true,      // false by default
  configurable: true,    // false by default
  writable: true         // false by default
});

This method is useful when you want to have more control while defining property. Property defined can be set as enumerable, configurable and writable by user.

Sanchay Kumar
  • 566
  • 5
  • 11
7

Your example shows an Object, not an Array. In that case, the preferred way to add a field to an Object is to just assign to it, like so:

arr.key3 = value3;
bdukes
  • 152,002
  • 23
  • 148
  • 175
7

We can add a key/value pair to a JavaScript object in many ways...

CASE - 1 : Expanding an object
Using this we can add multiple key: value to the object at the same time.

const rectangle = { width: 4, height: 6 };
const cube = {...rectangle, length: 7};
const cube2 = {...rectangle, length: 7, stroke: 2};
  console.log("Cube2: ", cube2);
  console.log("Cube: ", cube);
  console.log("Rectangle: ", rectangle);

CASE - 2 : Using dot notation

var rectangle = { width: 4, height: 6 };
rectangle.length = 7;
console.log(rectangle);

CASE - 3 : Using [square] notation

var rectangle = { width: 4, height: 6 };
    rectangle["length"] = 7;
    console.log(rectangle);
Rohit Tagadiya
  • 3,373
  • 1
  • 25
  • 25
6

You can either add it this way:

arr['key3'] = value3;

or this way:

arr.key3 = value3;

The answers suggesting keying into the object with the variable key3 would only work if the value of key3 was 'key3'.

wombleton
  • 8,336
  • 1
  • 28
  • 30
6

A short and elegant way in next Javascript specification (candidate stage 3) is:

obj = { ... obj, ... { key3 : value3 } }

A deeper discussion can be found in Object spread vs Object.assign and on Dr. Axel Rauschmayers site.

It works already in node.js since release 8.6.0.

Vivaldi, Chrome, Opera, and Firefox in up to date releases know this feature also, but Mirosoft don't until today, neither in Internet Explorer nor in Edge.

xyxyber
  • 109
  • 1
  • 7
6

You can create a new object by using the {[key]: value} syntax:

const foo = {
  a: 'key',
  b: 'value'
}

const bar = {
  [foo.a]: foo.b
}

console.log(bar); // {key: 'value'}
console.log(bar.key); // value

const baz = {
  ['key2']: 'value2'
}

console.log(baz); // {key2: 'value2'}
console.log(baz.key2); // value2

With the previous syntax you can now use the spread syntax {...foo, ...bar} to add a new object without mutating your old value:

const foo = {a: 1, b: 2};

const bar = {...foo, ...{['c']: 3}};

console.log(bar); // {a: 1, b: 2, c: 3}
console.log(bar.c); // 3
Jonathan Stellwag
  • 3,843
  • 4
  • 25
  • 50
4

Either obj['key3'] = value3 or obj.key3 = value3 will add the new pair to the obj.

However, I know jQuery was not mentioned, but if you're using it, you can add the object through $.extend(obj,{key3: 'value3'}). E.g.:

var obj = {key1: 'value1', key2: 'value2'};
$('#ini').append(JSON.stringify(obj));

$.extend(obj,{key3: 'value3'});

$('#ext').append(JSON.stringify(obj));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="ini">Initial: </p>
<p id="ext">Extended: </p>

jQuery.extend(target[,object1][,objectN]) merges the contents of two or more objects together into the first object.

And it also allows recursive adds/modifications with $.extend(true,object1,object2);:

var object1 = {
  apple: 0,
  banana: { weight: 52, price: 100 },
  cherry: 97
};
var object2 = {
  banana: { price: 200 },
  durian: 100
};
$("#ini").append(JSON.stringify(object1));    

$.extend( true, object1, object2 );
 
$("#ext").append(JSON.stringify(object1));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="ini">Initial: </p>
<p id="ext">Extended: </p>
Armfoot
  • 4,663
  • 5
  • 45
  • 60
-1

In order to prepend a key-value pair to an object so the for in works with that element first do this:

    var nwrow = {'newkey': 'value' };
    for(var column in row){
        nwrow[column] = row[column];
    }
    row = nwrow;
relipse
  • 1,730
  • 1
  • 18
  • 24