Last active
August 29, 2015 14:13
-
-
Save z5h/504f4cce5672f918901e to your computer and use it in GitHub Desktop.
Get the result of updating a Javascript object while treating it as immutable.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Get the result of updating `obj` with `props`, while treating `obj` | |
* as immutable. | |
*/ | |
var update = function(obj, props){ | |
var keys = Object.keys(props), | |
key, | |
changed = false, | |
i; | |
//if props makes no changes, just return obj | |
for (i = 0; i<keys.length; i++){ | |
key = keys[i]; | |
if (props[keys] !== obj[keys] || !(key in obj)){ | |
changed = true; | |
break; | |
} | |
} | |
if (!changed){ | |
return obj; | |
} | |
//we can't set constructor. so traverse the prototype chain until | |
//we | |
// a) find something with a constructor, or, | |
// b) hit null | |
var root = obj; | |
var hasOwnProperty = Object.prototype.hasOwnProperty; | |
while(root !== null && !hasOwnProperty.call(root, 'constructor')) { | |
root = Object.getPrototypeOf(root); | |
} | |
//our return object will have root as it's prototype | |
var result = Object.create(root); | |
//if something in obj's prototype chain has overridden root, | |
//then apply that change to the return object | |
for (key in obj){ | |
if (root === null || !(key in root && root[key] === obj[key])){ | |
result[key] = obj[key]; | |
} | |
} | |
//finally, copy everything from props into the result | |
for (i=0; i<keys.length; i++){ | |
key = keys[i]; | |
result[key] = props[key]; | |
} | |
return result; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment