Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

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
This page is out of date. Refresh to see the latest.
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.