I need a simple function to map a list of primitive properties from one object to another. I wrote one myself, but I guess there's already a proven method to achieve this.
var mapProperties = function (props, from) {
var to = {};
for (var i = 0; i < props.length; i++) {
to[props[i]] = from[props[i]];
}
return to;
}
Then use the function like:
var fromObj = {
foo: "foo",
bar: 1
}
var toObj = mapProperties(['foo', 'bar'], fromObj);
Any better ideas?
If you are not looking to DeepClone, Then you can use Object.assign
to copy the values of all enumerable own properties from one or more source objects to a target object.
var fromObj = {
foo: "foo",
bar: 1
}
var targetObject = Object.assign({}, fromObj);
console.log(targetObject);
For Deep Cloning, you can use the JSON.parse
and JSON.stringify
methods.
var fromObj = {
foo: "foo",
bar: 1,
deepClone : {
newProp : 2
}
}
var targetObject = JSON.parse(JSON.stringify(fromObj));
targetObject.deepClone.newProp = 4;
console.log(targetObject);
There are a couple ways to clone. If all you need is a shallow clone (your object only contains one level of primitives), Object.assign()
is a handy way to do it:
const fromObj = { a: 1, b: 2, c: 3 };
const toObj = Object.assign({}, fromObj);
The Object.assign()
function basically says "Assign all properties from the other objects to the first one". By making the first one an empty object, it is effectively a clone.
If you need a more controlled copy, you can use Object.keys()
so you don't have manually have an array that lists properties:
// concise example using reduce and assign
const cloneA = obj => Object.keys(obj).reduce((result, key) => Object.assign(result, { [key]: obj[key] }), {});
// using a for-loop
const cloneB = obj => {
const result = {};
const keys = Object.keys(obj);
for(let i in keys) {
result[keys[i]] = obj[keys[i]];
}
return result;
}
const fromObj = { a: 1, b: 2, c: 3 };
console.log(cloneA(fromObj));
console.log(cloneB(fromObj));
If you need to deal with anything other then primitives, you want a deep clone function. There are lots of libraries with them out there, so I won't re-implement one here, but basically it's a recursive version of one of my clone functions that checks if it's a primitive or not before the copy.
Here's an implementation that only copies primitives, following the convention of Object.assign()
:
function filterPrimitives (key) {
return !(this[key] instanceof Object)
}
function clonePrimitives (target) {
var sources = Array.from(arguments).slice(1)
sources.forEach(function (source) {
var ownKeys = Object.getOwnPropertyNames(source)
var primitiveKeys = ownKeys.filter(filterPrimitives, source)
primitiveKeys.forEach(function (key) {
target[key] = source[key]
})
})
return target
}
var target = {};
var source = {
a: 'test',
b: /test/,
c: 5,
d: null,
e: undefined,
f: {},
g: []
}
clonePrimitives(target, source, { a: 'override' })
console.log(target)
If you want a more efficient approach, use for loops instead of forEach()
:
function clonePrimitives (target) {
var i, j, source, ownKeys, key
for (i = 1; i < arguments.length; i++) {
source = arguments[i]
ownKeys = Object.getOwnPropertyNames(source)
for (j = 0; j < ownKeys.length; j++) {
key = ownKeys[j]
if (!(source[key] instanceof Object)) {
target[key] = source[key]
}
}
}
return target
}
var target = {};
var source = {
a: 'test',
b: /test/,
c: 5,
d: null,
e: undefined,
f: {},
g: []
}
clonePrimitives(target, source, { a: 'override' })
console.log(target)
And lastly, an equivalent ES6 approach that makes things a little nicer:
function clonePrimitives (target) {
for (let source of Array.from(arguments).slice(1)) {
for (let key of Object.getOwnPropertyNames(source)) {
if (!(source[key] instanceof Object)) {
target[key] = source[key]
}
}
}
return target
}
let target = {};
let source = {
a: 'test',
b: /test/,
c: 5,
d: null,
e: undefined,
f: {},
g: []
}
clonePrimitives(target, source, { a: 'override' })
console.log(target)