Skip to content

Loading…

Extend recursively #379

Closed
wants to merge 5 commits into from

2 participants

@BenHall

_.extend handles merges source sub-hash elements with the destination property. Previously it would override the sub-items of the destination property with the source.

@BenHall

I added support for arrays in commit 83133be but I'm not 100% sure if this is a good idea.

@jashkenas
Owner

Yep -- this is extremely unreliable, which is why Underscore doesn't do it. If you'd like to take a look at the kind of thing that would be necessary to do this in a foolproof fashion, check out _.isEqual.

@jashkenas jashkenas closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Showing with 16 additions and 2 deletions.
  1. +4 −0 test/objects.js
  2. +12 −2 underscore.js
View
4 test/objects.js
@@ -39,6 +39,10 @@ $(document).ready(function() {
ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps');
result = _.extend({}, {a: void 0, b: null});
equals(_.keys(result).join(''), 'b', 'extend does not copy undefined values');
+ same(_.extend({x:'x', a:{b:'c'}}, { a: { d: 'e' } }).a, {b:'c', d:'e'}, 'can extend an object recursively when source property is a hash');
+ same(_.extend({x:'x'}, { a: { b: 'c' } }).a, {b:'c'}, 'can extend an object recursively when destination does not exist');
+ same(_.extend({x:'x', a:[1,2,3]}, { a:[4] }).a, [1,2,3,4], 'can merge arrays');
+ same(_.extend({x:'x', a:{b:'c'}}, { a:[4] }).a, [4], 'overrides destination with source if types are different');
});
test("objects: defaults", function() {
View
14 underscore.js
@@ -644,8 +644,18 @@
// Extend a given object with all the properties in passed-in object(s).
_.extend = function(obj) {
each(slice.call(arguments, 1), function(source) {
- for (var prop in source) {
- if (source[prop] !== void 0) obj[prop] = source[prop];
+ for (var prop in source) if (!source.hasOwnProperty || source.hasOwnProperty( prop )) {
+ if (source[prop] !== void 0) {
+ if(obj[prop] != undefined && _.isObject(source[prop]) && !_.isArray(source[prop])) {
+ _.extend(obj[prop], source[prop]);
+ }
+ else if(_.isArray(obj[prop]) && _.isArray(source[prop])) {
+ obj[prop] = _.union(obj[prop], source[prop]);
+ }
+ else {
+ obj[prop] = source[prop];
+ }
+ }
}
});
return obj;
Something went wrong with that request. Please try again.