Assign object values only using Object.assign

I have two objects. One serves as the original source object, while the other is a deep copy of the source object with potentially different values. For example:

{
  id: 123,
  people: [{
      name: "Bob",
      age: 50
   }, {
      name: "Alice",
      age: 40
  }]
}

and

{
  id: 123,
  people: [{
      name: "Bob",
      age: 51 // Bob is now older
   }, {
      name: "Alice",
      age: 40
  }]
}

Keep in mind that the object has multiple nested keys, objects and arrays.

My goal is to update the values (and only the values) from the modified copy back onto the original source object.

The key aspect here is to retain the original reference points of the source object. This means I cannot use either of the following methods:

sourceObject = updatedCopiedObject;

as it would completely replace the source object and disrupt its references

Object.assign(sourceObject, updatedCopiedObject);

since this would lead to property overwriting, violating the need to maintain original references.

What I require is the functionality of Object.assign without property overwriting - simply updating matching properties with new values.

Currently, I am unaware of any built-in method capable of achieving this recursive/deep value-changing process. While I can create a custom method to address this, I am curious if there exists a pre-existing solution to this problem.

Answer №1

Unfortunately, I have not come across any existing built-in functions that handle this kind of recursive/deep process. While I am capable of creating a custom method to tackle this issue, I was hoping to discover an alternative solution beforehand.

Regrettably, none exist at present.

Answer №2

One way to iterate through the properties and values of an object is by using Object.entries(). This method returns key-value pairs of an object as an array. If a value itself is an object, you can recursively call the same function to reassign that property's value. Otherwise, simply set the value to be the same as the source object's property value.

let source = {
  id: 123,
  people: [{
      name: "Bob",
      age: 50
   }, {
      name: "Alice",
      age: 40
  }]
}

let copy = {
  id: 123,
  people: [{
      name: "Bob",
      age: 51 // Bob is older now
   }, {
      name: "Alice",
      age: 40
  }]
}

const reassign = (sourceObj, copyObj) =>{
  for (let [key, prop] of Object.entries(copyObj)) {
    if (typeof prop !== "object") {
      sourceObj[key] = prop;
    } else {
      reassign(sourceObj[key], prop)
    }
  }
  return [sourceObj, copyObj]
}

console.log(reassign(source, copy));

Answer №3

To assign the value, a combination of iterative and recursive methods can be employed.

This method examines the source object, creates new target properties as needed, and assigns the value if no nested object is detected.

function assignValue(target, source) {
    Object.keys(source).forEach(function(key) {
        if (source[key] && typeof source[key] === 'object') {
            return assignValue(target[key] = target[key] || Array.isArray(source[key]) ? [] : {}, source[key]);
        }
        if (target[key] !== source[key]) {
            target[key] = source[key];
        }
    });
}

var obj1 = { id: 123, people: [{ name: "Bob", age: 50 }, { name: "Alice", age: 40 }] }, obj2 = { id: 123, people: [{ name: "Bob", age: 51 }, { name: "Alice", age: 40 }] };

assignValue(obj1, obj2);
console.log(obj1);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Answer №4

After reading guest271314's explanation, I was able to create a modified recursive function to transfer only the "values" from one object to another. In my specific scenario, I had to make adjustments to handle arrays nested within the objects:

copyValues (target = {}, source) {
  let newValue = null
  let keysArray = Object.keys(source)
  for (let keyName of keysArray) {
    newValue = source[keyName]
    if (typeof newValue === 'object' && newValue !== null) {
      if (Object.prototype.toString.call(newValue) === '[object Array]') {
        target[keyName] = newValue
      } else {
        copyValues(target[keyName], newValue)
      }
    } else {
      target[keyName] = newValue
    }
  }
  return target
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Discovering the country associated with a country code using ngx-intl-tel-input

In my application, I am trying to implement a phone number field using this StackBlitz link. However, I have observed that it is not possible to search for a country by typing the country code (e.g., +231) in the country search dropdown. When I type a coun ...

Deactivating elements on a website

Is there a way to prevent multiple transactions due to unintended repeated clicks on a button by disabling all webpage elements when the button is clicked? Suggestions include using a div that can be layered on top of the elements when the button is click ...

What is the best way to establish a conditional statement that ensures ajax fetches the correct XML document?

I am trying to create a dynamic code that fetches an XML file and displays it as a drop-down list based on a condition. If the condition matches study1, then the code should select ctc3.xml; otherwise, it should choose ctc5.xml. Previously, my code was wo ...

Issues with AngularJS functionality have been noticed in Chrome browsers on both Mac and Windows platforms, with Safari being

As I begin my journey into learning AngularJS, I encountered an unusual issue. The code snippet below is taken from an online tutorial on Github. Interestingly, the code functions flawlessly on Safari (MAC) but fails to load on Chrome. The same problem p ...

How to Upload Your Avatar Image with the Stream-Chat API from GetStream.io

I am currently in the process of developing a Stream-Chat API project and I want to allow users to upload images directly from their devices. Upon testing, everything seems to be working fine, but the uploaded image is not displayed - only the default avat ...

Regularly updating a book's interactive pages with turn.js technology

I experimented with generating dynamic content in turn.js using the sample provided here. This is an excerpt of the code I have written: <body> <div id="paper"> </div> </body> <script type="text/javascript"> $(win ...

Accessing data from a JSON file within a JavaScript program

Here's the scenario: I have created a function that reads my JSON file and returns the value found at the end. This is how my files are organized: https://i.sstatic.net/TMeXVHNJ.png Below is my script.js file: async function readJSONFile(path) { ...

Chrome fails to apply CSS to Polymer 2 web component

The implementation of my web component in Polymer v2 is causing a styling issue specifically in Google Chrome. Despite including a CSS file that defines a style called n-action-button, the styling is not being applied to the content of the web component in ...

What is the best way to incorporate a transition effect into a flex item with a specified max-width, where the width adjustments are managed by a child div?

The example below demonstrates a situation where the child's width grows with a smooth transition, but the parent's width abruptly changes! What I aim for is to have both the child's width and the parent's width transition smoothly. I ...

Display the console.log output directly on the document instead of the console

My HTML file is super simple and only includes this code: <html> <head> <script defer src="./bundle_ACTUAL.js"></script> </head> </html> After running ./bundle_ACTUAL.js, I see the output in th ...

React component fails to render even after successful authentication check

Trying to set up a secure route for my application, I encountered an issue with React Hooks where the state is not updated directly. This causes a problem when trying to redirect unauthenticated users, as the initial render treats them as not logged in and ...

The href attribute is not functioning correctly on Internet Explorer version 8

When dynamically generating HTML and appending the response to a DIV, here is the jQuery code: {% elif topic|length < 1 or topic.user_exhausted_attempts %} $('.questionHolder').hide(); var html = '<section class="span9">&a ...

Achieve the effect of "background-attachment: fixed" using a div element

I am attempting to replicate a similar effect as seen here, which is accomplished using the CSS property background-attachment:fixed. However, I want to achieve this effect using div elements instead. For instance, could I apply this effect to an h1 tag? ...

The API has been triggered twice

I am currently working on a React component where I have implemented an API call using the useEffect hook with an empty dependency array. However, I noticed that the API is being called twice and I can't seem to find the reason behind it. import { use ...

What is the best approach for sending a single mail value to the backend when there are multiple inputs in an Axios post request?

Would like assistance with a feature where only the input fields filled by the user are sent to the backend? Here, I have 3 email input fields and want to send only the filled ones. How can this be achieved? const App =() => { const [email,setEmail] ...

What is the best way to apply lodash's max function to a jQuery array?

I'm having trouble extracting the maximum number of rows from two tables. My variable maxRows ends up being a tbody jQuery element instead of the actual maximum value. I've experimented with both the pluck syntax and the long form, but both metho ...

Tips for integrating a custom class file in NestJS without compromising the NestJS conventions

In my nestjs project, I have a custom Crypto class implementation which utilizes bcrypt for hashing and comparing passwords. import * as bcrypt from 'bcrypt'; export class Crypto { constructor() { } public async hash(target: string, sal ...

Deregister channel listener

My application has a functionality where users can subscribe to Twilio chat channels. When a user clicks on a channel, the chat opens up, messages are loaded, and the user is subscribed to receive new messages using this.state.channel.on('messageAdded ...

Using React.js to dynamically display or hide elements generated within a component

I'm currently working on a project where I need to dynamically generate form fields based on certain criteria. Specifically, I want to hide some fields and only show them when other specific conditions are met, a common requirement in form designs. Fo ...

Creating Positioning Magic with HTML Elements

Currently working on an ASP.NET web app that utilizes a Master, with just a GridView at the bottom and a DIV at the top for further development. The goal is to keep the top DIV or header fixed while scrolling, ensuring it remains in place at the top of th ...