Search code examples
javascriptecmascript-6functional-programmingecmascript-5

Modify JS Object in Pure Way


I have a function that transforms a JS object. It derives a new property from an existing one, then deletes the original property. Essentially something like this:

/** Derives "capName" property from "name" property, then deletes "name" */
function transform(person) {
  person["capName"] = person["name"].toUpperCase();
  delete person["name"];
  return person;
}

var myPerson = {
  name: "Joe",
  age: 20
};

var newPerson = transform(myPerson);

console.log(myPerson, newPerson);

The function returns the desired newPerson object, but also modifies the original myPerson object. I would rather do this in a pure way, that doesn't modify the original myPerson object.

Note: I really need to be ES5 compatible, but I'd like to see the ES6 solution as well.


Solution

  • For ES5 compatibility, you can use JSON.parse(JSON.stringify(person)). Be aware that methods attached to person are lost on the way because they cannot properly be JSON.stringifyed.

    /** Derives "capName" property from "name" property, then deletes "name" */
    function transform(person) {
      var obj = JSON.parse(JSON.stringify(person));
      obj["capName"] = obj["name"].toUpperCase();
      delete obj["name"];
      return obj;
    }
    
    var myPerson = {
      name: "Joe",
      age: 20
    };
    
    var newPerson = transform(myPerson);
    
    console.log(myPerson, newPerson);

    If you want to retain methods, just iterate over the object keys:

    /** Derives "capName" property from "name" property, then deletes "name" */
    function transform(person) {
      var obj = {};
      for (var key in person) {
        obj[key] = person[key];
      }
      obj["capName"] = obj["name"].toUpperCase();
      delete obj["name"];
      return obj;
    }
    
    var myPerson = {
      name: "Joe",
      age: 20
    };
    
    var newPerson = transform(myPerson);
    
    console.log(myPerson, newPerson);

    Be aware that none of the methods presented does a deep clone. For that, I'd recommend you use something like lodash's _.clone(obj, { deep: true });