-
Notifications
You must be signed in to change notification settings - Fork 27.4k
feat(angular.extend) - Simple non-breaking change to support deep extend #10507
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -333,22 +333,32 @@ function setHashKey(obj, h) { | |
* Extends the destination object `dst` by copying own enumerable properties from the `src` object(s) | ||
* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so | ||
* by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`. | ||
* Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy). | ||
* Note: Pass `true` in as the last argument to perform a recursive merge (deep copy). | ||
* | ||
* @param {Object} dst Destination object. | ||
* @param {...Object} src Source object(s). | ||
* @returns {Object} Reference to `dst`. | ||
*/ | ||
function extend(dst) { | ||
var h = dst.$$hashKey; | ||
var argsLength = arguments.length; | ||
var isDeep = (argsLength >= 3) && (arguments[argsLength - 1] === true); | ||
|
||
for (var i = 1, ii = arguments.length; i < ii; i++) { | ||
if (isDeep) --argsLength; | ||
|
||
for (var i = 1; i < argsLength; i++) { | ||
var obj = arguments[i]; | ||
if (obj) { | ||
var keys = Object.keys(obj); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That said, I really think we should only be taking this path if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For instance: Object.keys(4); // will return the own-enumerable-property-keys of `new Number(4);` --- that's not very useful! It won't have any own properties. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, in ES5 it will throw for all non-objects, which is not very useful! So WebKit/JSC would throw here anyways. Newer browsers will take the ES6 path and convert the primitive ToObject, and do the wrong stuff with it. |
||
for (var j = 0, jj = keys.length; j < jj; j++) { | ||
var key = keys[j]; | ||
dst[key] = obj[key]; | ||
var src = obj[key]; | ||
|
||
if (isDeep && isObject(dst[key])) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If |
||
src = extend(dst[key], src, true); | ||
} | ||
|
||
dst[key] = src; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we just copied everything from |
||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -223,6 +223,21 @@ describe('angular', function() { | |
// make sure we retain the old key | ||
expect(hashKey(dst)).toEqual(h); | ||
}); | ||
|
||
it('should perform deep extend when last argument is true', function() { | ||
var src = { foo: { bar: 'foobar', age: 10, nothing: null, undef: void 0 }}, | ||
dst = { foo: { bazz: 'foobazz' }}; | ||
extend(dst, src, true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add a test case where There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also add some tests where properties have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add the tests I've been asking for, and address all of the comments I've brought up --- then we can land this. You can avoid the complicated squash in the future by just doing |
||
expect(dst).toEqual({ | ||
foo: { | ||
bar: 'foobar', | ||
bazz: 'foobazz', | ||
age: 10, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not what I said before. Don't worry about the tests, I'll add some when I check this in :\ |
||
nothing: null, | ||
undef: void 0 | ||
} | ||
}); | ||
}); | ||
}); | ||
|
||
describe('shallow copy', function() { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You misunderstood me in that last commit --- I mean on line 353, the condition should not be
if (obj)
, it should beif (isObject(obj) || isFunction(obj))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make this change, please.