Compare Two JavaScript Objects and Get the Updated Keys

Where a Value of the Key Has Changed

We have two similar JavaScript objects, and we are interested in finding which of the key(s), if any, have changed at the first level. A key in the object could hold any data type in its value, including array and object, and it could also be deeply nested. The change could mean anything, such as added, added to, removed, removed from, modified, or shuffled etc.

This kind of key identification might be required in cases where you need to compare the old and new state, such as previous and new filters, and figure out what exactly changed.

Below is the code to find one key that has changed its value between the objects. Further down, there’s a modified code to get more than one keys that are changed.

The Code

You could write your own comparison or unique-finder code for array and objects. But as it gets fairly complicated with more deeply nested levels, and thus amounts to reinventing the wheel, I’d prefer lodash methods isEqual and uniq. The code is as follows:

// es module
import { isEqual, uniq } from "lodash";

// OR commonJS
const _ = require("lodash");
const { isEqual, uniq } = _;

const getUpdatedKey = (oldData, newData) => {
  const data = uniq([...Object.keys(oldData), ...Object.keys(newData)]);

  for(const key of data){
    if(!isEqual(oldData[key], newData[key])){
      return key;
    }
  }

  return null;
}

The Code Explained:

  • Get the unique keys from both objects in a flat array.
  • Loop through the array and for each key check if data against that key in both objects isEqual to one another.
  • If not equal, it means the key value has changed. So, return the key (stopping the loop in its track).
  • If nothing has changed, return null.

Example Data & Results

let oldObj;
let newObj;

oldObj = {
  countries: ["Pakistan", "India", "Japan", "England", "United States"],
  nationalities: ["American", "British", "Pakistani", "Indian", "Chinese"]
};

newObj = {
  countries: ["Pakistan", "India", "Japan", "England"],
  nationalities: ["American", "British", "Pakistani", "Indian", "Chinese"]
}

console.log(getUpdatedKey(oldObj, newObj)); // countries

oldObj = {
  countries: ["Pakistan", "India", "Japan", "England", "United States"],
  nationalities: ["American", "British", "Pakistani", "Indian", "Chinese"]
};

newObj = {
  countries: ["Pakistan", "India", "Japan", "United States", "England"],
  nationalities: ["American", "British", "Pakistani", "Indian", "Chinese"]
}

console.log(getUpdatedKey(oldObj, newObj)); // countries

oldObj = {
  countries: ["Pakistan", "India", "Japan", "England", "United States"],
  nationalities: ["American", "British", "Pakistani", "Indian", "Chinese"]
};

newObj = {
  countries: ["Pakistan", "India", "Japan", "England", "United States"],
  nationalities: ["American", "British", "Pakistani", "Indian"]
}

console.log(getUpdatedKey(oldObj, newObj)); // nationalities

oldObj = {
  id: "ioj86bndom",
  name: {
    first: "John",
    middle: "Montgomery",
    last: "Smith"
  },
  address: {
    street: "660 K St",
    city: "San Diego",
    state: "California",
    country: "United States"
  }
};

newObj = {
  id: "ioj86bndom",
  name: {
    first: "John",
    middle: "Montgomery",
    last: "Smith"
  },
  address: {
    street: "4914 U.S. 220 Business",
    city: "Randleman",
    state: "Nebraska",
    country: "United States"
  }
};

console.log(getUpdatedKey(oldObj, newObj)); // address


oldObj = {
  id: "ioj86bndom",
  name: {
    first: "John",
    middle: "Montgomery",
    last: "Smith"
  },
  address: {
    street: "660 K St",
    city: "San Diego",
    state: "California",
    country: "United States"
  }
};

newObj = {
  id: "ioj86bndom",
  name: {
    first: "John",
    last: "Smith"
  },
  address: {
    street: "4914 U.S. 220 Business",
    city: "Randleman",
    state: "Nebraska",
    country: "United States"
  }
};

console.log(getUpdatedKey(oldObj, newObj)); // name

The Code for Getting Multiple Updated Keys

The above code will only identify the first key that fits the criteria. We could slightly modify it to return more than one keys by keeping an array, pushing into it, and returning it at the end:

const getUpdatedKeys = (oldData, newData) => {
  const data = uniq([...Object.keys(oldData), ...Object.keys(newData)]);
  const keys = [];
  for(const key of data){
    if(!isEqual(oldData[key], newData[key])){
      keys.push(key);
    }
  }

  return keys;
}

Examples for Multiple Updated Keys



oldObj = {
  id: "ioj86bndom",
  name: {
    first: "John",
    middle: "Montgomery",
    last: "Smith"
  },
  address: {
    street: "660 K St",
    city: "San Diego",
    state: "California",
    country: "United States"
  }
};

newObj = {
  id: "ioj86bndom",
  name: {
    first: "John",
    last: "Smith"
  },
  address: {
    street: "4914 U.S. 220 Business",
    city: "Randleman",
    state: "Nebraska",
    country: "United States"
  }
};

console.log(getUpdatedKeys(oldObj, newObj)); // [ 'name', 'address' ]




oldObj = {
  id: "ioj86bndom",
  name: {
    first: "John",
    middle: "Montgomery",
    last: "Smith"
  },
  address: {
    street: "660 K St",
    city: "San Diego",
    state: "California",
    country: "United States",
    somethingNested: {
      a: {
        b: true
      }
    }
  }
};

newObj = {
  id: "ioj86bndom",
  name: {
    first: "John",
    middle: "Montgomery",
    last: "Smith"
  },
  address: {
    street: "660 K St",
    city: "San Diego",
    state: "California",
    country: "United States",
    somethingNested: {
      a: {
        b: false
      }
    }
  }
};


console.log(getUpdatedKeys(oldObj, newObj)); // [ 'address' ]

See also