My simple code
const ob1 = {
a: 'pokushevski',
b: '2001',
};
const obj2 = {
obj1: {},
c: '1999',
};
const result = Object.assign(ob1, obj2);
console.log(result);
console.log(Object.getOwnPropertyNames(result));
Output
{ a: 'pokushevski', b: '2001', obj1: {}, c: '1999' }
[ 'a', 'b', 'obj1', 'c' ]
It seems that obj1 in result appears just as any other attribute,without having any reference to const obj1.
Why?
What you are doing right now is basically merging ob1 (without 'j') with obj2 (with 'j'), and since obj1 (with 'j') is an empty object inside of obj2, it gets added as a property on the resulting merged object.
What else did you expect, and can we help in getting you there?
Maybe you actually made a typo and wanted the first object ob1 to be named obj1 instead, then to be used as a property within obj2 and finally merge the two objects?
If so you co do:
const obj1 = {
a: 'pokushevski',
b: '2001',
};
const obj2 = {
obj1, // shorthand syntax, property will be named the same as the const
c: '1999',
};
// avoid mutation by using a new object as the target
const result = Object.assign({}, obj1, obj2);
// Display result and property names
console.log(result);
console.log(Object.getOwnPropertyNames(result));
If you only wanted to add obj1 within obj2 you don't need Object.assign
Watch out for what's mutable
With the code above, the original obj1 gets modified whenever you update result.obj1 properties. Try to update result.obj1.a and then console.log(obj1)
If you want to prevent this, you can use destructuring like so:
const obj1 = {
a: 'pokushevski',
b: '2001',
};
// Create a shallow copy of `obj1` to prevent mutating the original
// object by updating `obj2.obj1` properties
const obj2 = {
obj1: {...obj1},
c: '1999',
};
// Avoid mutating the original `obj1` by using a new object as the target
const result = Object.assign({}, obj1, obj2);
// Display result and property names
console.log(result);
console.log(Object.getOwnPropertyNames(result))
If you really want to keep using Object.assign instead of destructuring you can replace obj1: {...obj1} by obj1: Object.assign({}, obj1)
I guess that you want ob1 to be obj1 inside obj2
Then this is a way to do it:
const ob1 = {
a: 'pokushevski',
b: '2001',
};
const obj2 = {
obj1: {},
c: '1999',
};
const result = Object.assign({}, obj2);
Object.assign(result.obj1, ob1);
console.log(result);
console.log(Object.getOwnPropertyNames(result));
I am trying to return new object with selected keys - reqProps. I managed to do it with fixes props prop1, prop3 and now want to be able to pass reqProps array values to replace prop1, prop3. I tried function, and string literals and few 'hacks'. None of them worked
const data = [
{
prop1: 1,
prop2: 2,
prop3: 3
},
{
prop1: 10,
prop2: 20,
prop3: 30
},
{
prop2: 200,
prop4: 400
},
{
prop3: 3000
}
];
// to return properties for the following...
const reqProps = ['prop2','prop3','prop4'];
// current implementation fixing return object with prop1, prop3
const obj = data.map(({prop1, prop3}) => {
return {prop1, prop3};
});
The result of obj for the moment is
[{"prop1":1,"prop3":3},{"prop1":10,"prop3":30},{},{"prop3":3000}]
I do not want to use loops, quite like the 'power' of destructuring! ;)
If you insist on destructuring, you have to use eval:
const reqProps = ['prop2','prop3','prop4'];
const literalString = '{'+reqProps.join(',')+'}';
const obj = data.map(new Function(literalString, 'return '+literalString));
You really should use a loop - you can also hide it in a helper function or just use reduce.
As #Bergi suggests, you'd better use loops in some way.
Here's a variant with implicit loops:
data.map(o => reqProps.filter(p => p in o)
.reduce((acc, p) => ({...acc, [p]: o[p]}), {}))
For example if I have two objects:
var foo = {
x: "bar",
y: "baz"
}
and
var oof = {}
and I wanted to transfer the x and y values from foo to oof. Is there a way to do that using the es6 destructuring syntax?
perhaps something like:
oof{x,y} = foo
While ugly and a bit repetitive, you can do
({x: oof.x, y: oof.y} = foo);
which will read the two values of the foo object, and write them to their respective locations on the oof object.
Personally I'd still rather read
oof.x = foo.x;
oof.y = foo.y;
or
['x', 'y'].forEach(prop => oof[prop] = foo[prop]);
though.
IMO this is the easiest way to accomplish what you're looking for:
let { prop1, prop2, prop3 } = someObject;
let data = { prop1, prop2, prop3 };
// data === { prop1: someObject.prop1, ... }
Basically, destructure into variables and then use the initializer shorthand to make a new object. No need for Object.assign
I think this is the most readable way, anyways. You can hereby select the exact props out of someObject that you want. If you have an existing object you just want to merge the props into, do something like this:
let { prop1, prop2, prop3 } = someObject;
let data = Object.assign(otherObject, { prop1, prop2, prop3 });
// Makes a new copy, or...
Object.assign(otherObject, { prop1, prop2, prop3 });
// Merges into otherObject
Another, arguably cleaner, way to write it is:
let { prop1, prop2, prop3 } = someObject;
let newObject = { prop1, prop2, prop3 };
// Merges your selected props into otherObject
Object.assign(otherObject, newObject);
I use this for POST requests a lot where I only need a few pieces of discrete data. But, I agree there should be a one liner for doing this.
EDIT: P.S. -
I recently learned you can use ultra destructuring in the first step to pull nested values out of complex objects! For instance...
let { prop1,
prop2: { somethingDeeper },
prop3: {
nested1: {
nested2
}
} = someObject;
let data = { prop1, somethingDeeper, nested2 };
Plus, you could use spread operator instead of Object.assign when making a new object:
const { prop1, prop2, prop3 } = someObject;
let finalObject = {...otherObject, prop1, prop2, prop3 };
Or...
const { prop1, prop2, prop3 } = someObject;
const intermediateObject = { prop1, prop2, prop3 };
const finalObject = {...otherObject, ...intermediateObject };
No, destructuring does not support member expressions in shorthands but only plain propertynames at the current time. There have been talks about such on esdiscuss, but no proposals will make it into ES6.
You might be able to use Object.assign however - if you don't need all own properties, you still can do
var foo = …,
oof = {};
{
let {x, y} = foo;
Object.assign(oof, {x, y})
}
Other than Object.assign there is the object spread syntax which is a Stage 2 proposal for ECMAScript.
var foo = {
x: "bar",
y: "baz"
}
var oof = { z: "z" }
oof = {...oof, ...foo }
console.log(oof)
/* result
{
"x": "bar",
"y": "baz",
"z": "z"
}
*/
But to use this feature you need to use stage-2 or transform-object-rest-spread plugin for babel. Here is a demo on babel with stage-2
BabelJS plugin
If you are using BabelJS you can now activate my plugin babel-plugin-transform-object-from-destructuring (see npm package for installation and usage).
I had the same issue described in this thread and for me it was very exhausting when you create an object from a destructuring expression, especially when you have to rename, add or remove a property. With this plugin maintaining such scenarios gets much more easier for you.
Object example
let myObject = {
test1: "stringTest1",
test2: "stringTest2",
test3: "stringTest3"
};
let { test1, test3 } = myObject,
myTest = { test1, test3 };
can be written as:
let myTest = { test1, test3 } = myObject;
Array example
let myArray = ["stringTest1", "stringTest2", "stringTest3"];
let [ test1, , test3 ] = myArray,
myTest = [ test1, test3 ];
can be written as:
let myTest = [ test1, , test3 ] = myArray;
It's totally possible. Just not in one statement.
var foo = {
x: "bar",
y: "baz"
};
var oof = {};
({x: oof.x, y: oof.y} = foo); // {x: "bar", y: "baz"}
(Do note the parenthesis around the statement.)
But keep in mind legibility is more important than code-golfing :).
Source: http://exploringjs.com/es6/ch_destructuring.html#sec_assignment-targets
You can just use restructuring for that like this:
const foo = {x:"a", y:"b"};
const {...oof} = foo; // {x:"a", y:"b"}
Or merge both objects if oof has values:
const foo = {x:"a", y:"b"};
let oof = {z:"c"}
oof = Object.assign({}, oof, foo)
You can return the destructured object in an arrow function, and use Object.assign() to assign it to a variable.
const foo = {
x: "bar",
y: "baz"
}
const oof = Object.assign({}, () => ({ x, y } = foo));
You can destruct an object assigning directly to another object attribute.
Working example:
let user = {};
[user.name, user.username] = "Stack Overflow".split(' ');
document.write(`
1st attr: ${user.name} <br />
2nd attr: ${user.username}`);
You can work with destructing using variables with the same name of object attribute you want to catch, this way you don't need to do:
let user = { name: 'Mike' }
let { name: name } = user;
Use this way:
let user = { name: 'Mike' }
let { name } = user;
The same way you can set new values to object structures if they have the same attribute name.
Look this working example:
// The object to be destructed
let options = {
title: "Menu",
width: 100,
height: 200
};
// Destructing
let {width: w, height: h, title} = options;
// Feedback
document.write(title + "<br />"); // Menu
document.write(w + "<br />"); // 100
document.write(h); // 200
Try
var a = {a1:1, a2: 2, a3: 3};
var b = {b1:1, b2: 2, b3: 3};
const newVar = (() => ({a1, a2, b1, b2})).bind({...a, ...b});
const val = newVar();
console.log({...val});
// print: Object { a1: 1, a2: 2, b1: 1, b2: 2 }
or
console.log({...(() => ({a1, a2, b1, b2})).bind({...a, ...b})()});
I came up with this method:
exports.pick = function pick(src, props, dest={}) {
return Object.keys(props).reduce((d,p) => {
if(typeof props[p] === 'string') {
d[props[p]] = src[p];
} else if(props[p]) {
d[p] = src[p];
}
return d;
},dest);
};
Which you can use like this:
let cbEvents = util.pick(this.props.events, {onFocus:1,onBlur:1,onCheck:'onChange'});
let wrapEvents = util.pick(this.props.events, {onMouseEnter:1,onMouseLeave:1});
i.e., you can pick which properties you want out and put them into a new object. Unlike _.pick you can also rename them at the same time.
If you want to copy the props onto an existing object, just set the dest arg.
This is kind of cheating, but you can do something like this...
const originalObject = {
hello: 'nurse',
meaningOfLife: 42,
your: 'mom',
};
const partialObject = (({ hello, your }) => {
return { hello, your };
})(originalObject);
console.log(partialObject); // { hello: 'nurse', your: 'mom' }
In practice, I think you'd rarely want to use that though. The following is MUCH more clear... but not nearly as fun.
const partialObject = {
hello: originalObject.hello,
your: originalObject.your,
};
Another completely different route, which includes mucking with the prototype (careful now...):
if (!Object.prototype.pluck) {
Object.prototype.pluck = function(...props) {
return props.reduce((destObj, prop) => {
destObj[prop] = this[prop];
return destObj;
}, {});
}
}
const originalObject = {
hello: 'nurse',
meaningOfLife: 42,
your: 'mom',
};
const partialObject2 = originalObject.pluck('hello', 'your');
console.log(partialObject2); // { hello: 'nurse', your: 'mom' }
This is the most readable and shortest solution I could come up with:
let props = {
isValidDate: 'yes',
badProp: 'no!',
};
let { isValidDate } = props;
let newProps = { isValidDate };
console.log(newProps);
It will output { isValidDate: 'yes' }
It would be nice to some day be able to say something like let newProps = ({ isValidDate } = props) but unfortunately it is not something ES6 supports.
You can use JSON class methods to achieve it as follows
const foo = {
x: "bar",
y: "baz"
};
const oof = JSON.parse(JSON.stringify(foo, ['x','y']));
// output -> {x: "bar", y: "baz"}
Pass properties that need to be added to the resulting object as second argument to stringify function in an array format.
MDN Doc for JSON.stringify
This works in chrome 53.0.2785.89
let foo = {
x: "bar",
y: "baz"
};
let oof = {x, y} = foo;
console.log(`oof: ${JSON.stringify(oof)}`);
//prints oof: { "x": "bar", "y": "baz"}
It's not a beautiful way, nor I recommend it, but it's possible this way, just for knowledge.
const myObject = {
name: 'foo',
surname: 'bar',
year: 2018
};
const newObject = ['name', 'surname'].reduce(
(prev, curr) => (prev[curr] = myObject[curr], prev),
{},
);
console.log(JSON.stringify(newObject)); // {"name":"foo","surname":"bar"}
I am trying to convert all elements of a given key in a list of objects. The specific change is to convert an generic object to a Long object with the same values.
Input:
[obj1, obj2, obj3, ...]
Where each object looks like:
{
key1: value1, // value1 is an object
key2: value2
}
So the goal here is to get a very similar array, but where key1 is transformed from just object to a long object, in my example incremented by one.
Output:
[obj1, obj2, obj3]
Where each object is:
{
key1: value1, // value1 is now a Long object
key2: value2
}
I tried with mapping over the array and then spreading over the objects entries, but did not succeed.
Any help would be highly appreciated.
You don't really need to map here, unless you want to create one more new array. Simple loop would be enough, just update key1 or each object:
[obj1, obj2, obj3].forEach(obj => {
obj.key1 = obj.key1 + 1
})
Since the array holds object - any modification to object reflect the actual input being passed. You need to make a copy of your object and perform the logic.
Your logic,
var input = [obj1, obj2, obj3];
var output = input.map(function(obj){
obj.key1 = obj.key1 + 1;
return obj;
});
console.log(input[0]===output[0]); //true
Solution:
var output = input.map(function(obj){
var _objCopy = Object.assign({}, obj);
_objCopy.key1 = _objCopy.key1 + 1;
return _objCopy;
});
console.log(input[0]===output[0]); //false
how about dynamically first key of any object es6 way
const myObject0 = {
'foo1': { name: 'myNam1' },
'foo2': { name: 'myNam2' }
};
const myObject1 = {
'yo': { name: 'myNam1' },
'boh': { name: 'myNam2' }
};
[myObject0, myObject1].forEach(obj => {
let getFirstKey = Object.keys(obj)[0];
getFirstKey = getFirstKey + 1;
console.log(getFirstKey);
});
Thanks for all the answers guys.
I ended up with the following:
Given the input
[
{
key1: value1, // value1 is an object
key2: value2
},
{
key1: value1, // value1 is also an object
key2: value2
}
]
Solution:
I ended up with,
const testvar = [obj1, obj2, obj3].map((obj) => {
return {
...obj,
key1: new Long.fromValue(obj.key1)
}
});
console.log(testvar);
Which gives the output
[
{
key1: value1, // value1 is now a Long object
key2: value2
},
{
key1: value1, // value1 is also now a Long object
key2: value2
}
]