Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
object with some values as objects
var obj = {
name: "Simon",
age: "20",
clothing: {
style: "simple",
isDouche: false
}
}
@paopay

This comment has been minimized.

Copy link

commented Oct 7, 2015

if you're updating all attributes, you can just pass in a new object.

newObjAttrs = {
  name: "Bob",
  age: "21",
  clothing: {
    style: "douchy",
    isDouche: true
  }
};

function foo(obj, newObjAttrs) {
  var keys = Object.keys(obj);

  for(var i=0; i<keys.length; i++) {
    obj[keys[i]] = newObjAttrs[keys[i]];
  }

  return obj;
};
@arcin

This comment has been minimized.

Copy link

commented Oct 8, 2015

If you want a deep copy, heres a recursive way.

var obj = {
    name: "Simon",
    age: "20",
    clothing: {
        style: "simple",
        isDouche: false
    }
}
function deepCopy (oldObj, newObj) {
  newObj = newObj || {};
  for (var key in oldObj) {
    if (typeof obj[key] === 'object') {
      newObj[key] = {};
      thing(obj[key], newObj[key]);
    }
    newObj[key] = obj[key];
    }
  }
  return newObj;
}
@georgebonnr

This comment has been minimized.

Copy link

commented Oct 8, 2015

Depends on what attributes need to change, and how often.

ES6 examples:

const newObj = Object.assign({}, obj, {clothing:{style:"complex"}})
const newObj = {
  ...obj,
  ...{
    age: "21"
  }
}

also check out https://lodash.com/docs#merge

@elreimundo

This comment has been minimized.

Copy link

commented Oct 8, 2015

Just to clean up @arcin 's suggestion, which is good but which has three errors (assigning newObj without checking its type first, iterating over the prototype without checking hasOwnProperty, and calling an incorrect method thing instead of deepCopy)

function deepCopy (oldObj, newObj) {
    if (_isObject(oldObj)) {
        if ( !_isObject(newObj) ) newObj = {};
        _each(oldObj, function(key, attribute) {
            newObj[key] = deepCopy(attribute, newObj[key]);
        });
    } else {
        newObj = oldObj;
    }
    return newObj;
}

function _isObject(target) {
    return typeof target === 'object'  && target; // since typeof null === 'object'
}

function _has(object, key) {
    return object.hasOwnProperty(key);
}

function _each(object, callback) {
    for (var key in object) {
        if ( !_has(object, key) ) continue;
        callback(key, object[key]);
    }
}

results in the console:

var old = { foo: 'bar', baz: { qux: 'nested' } };
< undefined
var newObj = { name: 'test' };
< undefined
var result = deepCopy(old, newObj);
< undefined
result
< Object {name: "test", foo: "bar", baz: Object {qux: "nested"} }
result === newObj
< true

note that all of these naive implementations (including mine) will "fail" if you have any circular references, e.g.

var ouroboros = {};
ouroboros.self = ouroboros;

since you will kick off an infinite loop. These deep copies work only for acyclic graphs or trees.

result in console:

> var ouroboros = {};
< undefined
> ouroboros.self = ouroboros;
< Object {self: Object}
> var result = deepCopy(ouroboros);
< Uncaught RangeError: Maximum call stack size exceeded(…)
@arcin

This comment has been minimized.

Copy link

commented Oct 8, 2015

@elreimundo Thanks for clearing up those issues! I totally forgot to change thing to deepCopy when I renamed the function haha. @konamax123 Copying in JS is rough because there are a lot of subtleties to consider when duplicating the memory allocated to objects and their contents. If you want a solution free of headaches (for the most part) consider Immutable data structures. They use structural sharing so creating "copies" isn't really that expensive. A good library is Facebooks ImmutableJS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.