Home > OS >  JS Object.assign without adding additional key/value
JS Object.assign without adding additional key/value

Time:12-29

I am interested in to assign values to only those keys that are available in destination object from source object.

const destination= {
    name: "John Doe", 
    age: 24,
}
const source= {
    name: "Usman Khan", 
    age: 36,
    title: "Full stack developer",
    location: "Remote"
}

if I use Object.assign it merges both object same with the spread operator.

I am only interested to assign values to keys available in destination object i.e. Only Name and age, not to merge the two objects without loops and if conditions or any other efficient method.

CodePudding user response:

You still need some iterations.

const
    getProperty = object => key => ({ [key]: object[key] }),
    destination= { name: "John Doe", age: 24 },
    source= { name: "Usman Khan", age: 36, title: "Full stack developer", location: "Remote" };

Object.assign(
    destination, 
    ...Object
        .keys(destination)
        .map(getProperty(source))
);

console.log(destination);

CodePudding user response:

This can be done using Object.entries() and a forEach loop along with the in operator.

Object.entries() gives you an array of entries [key,value] in the object.

const destination= {
    name: "John Doe", 
    age: 24,
};
const source= {
    name: "Usman Khan", 
    age: 36,
    title: "Full stack developer",
    location: "Remote"
};

Object.entries(source).forEach( ([key,value]) => {
      if(key in destination) destination[key] = value;
});
console.log(destination);
console.log(source);

CodePudding user response:

Iterate over destination using for...in, while checking if every property is in source using Object#hasOwnProperty to update its value.

const 
  destination = { name: "John Doe", age: 24 },
  source = { name: "Usman Khan", age: 36, title: "Full stack developer", location: "Remote" };
  
for(const prop in destination) {
  if(source.hasOwnProperty(prop)) {
    destination[prop] = source[prop];
  }
}

console.log(destination);

CodePudding user response:

This problem can be reduced to:

  1. Find properties that exist on both destination and source.
  2. Assign these properties from source to destination.

Here is an example implementation:

const destination = { name: "John Doe", age: 24 };
const source = {
  name: "Usman Khan",
  age: 36,
  title: "Full stack developer",
  location: "Remote"
};

console.log(assignExisting(destination, source));

function assignExisting(destination, source) {
  const sourceKeys = allKeys(source);
  for (const key in destination) {
    if (sourceKeys.includes(key)) { // If in both destination and source
      destination[key] = source[key]; // then assign property
    }
  }
  
  return destination;
}
function allKeys(o) { // See excursus for why I use this
  const keys = [];
  for (const p in o) keys.push(p);
  return keys;
}

Excursus: Prototypes, properties and delete

JavaScript is prototype-based, which means that objects are or may have prototypes. Since prototypes are objects themselves, they naturally can have properties as well.

When an object and a prototype of it have a property of similar name, the object's property shadows the prototype's property. This does not override the prototype's property.

This means an object can have own properties and inherited properties. To find whether a property is an object's own, you can use Object.prototype.hasOwnProperty().

Simply assigning undefined to an object's property will however not delete it: It will still shadow the prototype's properties. To actually delete a property, use the delete operator:

function ExampleObject() {}
ExampleObject.prototype.value = "inherited";

const object = new ExampleObject();

console.log("object.value");
console.log("-Before shadowing: "   object.value);

object.value = "own";
console.log("-After shadowing: "   object.value);

object.value = undefined;
console.log("-After assigning undefined: "   object.value);

delete object.value;
console.log("-After deleting own property: "   object.value);

Object.keys() returns an array of own properties; for...in loops over all (own and inherited) properties.

Returning to the original question: Since we want to assign all properties that both destination and source have, we need to consider the inherited properties as well. Object.keys() won't allow us to do so, which is why I use my allKeys() function and a for...in loop.

  • Related