Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f683061

Browse files
committedDec 18, 2014
refactor(extend): apply caitp's review comments for good measure :)
Derpity doot Closes #10507
1 parent 5e927ee commit f683061

File tree

2 files changed

+70
-16
lines changed

2 files changed

+70
-16
lines changed
 

‎src/Angular.js

+18-12
Original file line numberDiff line numberDiff line change
@@ -333,37 +333,43 @@ function setHashKey(obj, h) {
333333
* Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
334334
* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
335335
* by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.
336-
* Note: Pass `true` in as the last argument to perform a recursive merge (deep copy).
337336
*
338337
* @param {Object} dst Destination object.
339338
* @param {...Object} src Source object(s).
339+
* @param {boolean=} deep if the last parameter is set to `true`, objects are recursively merged
340+
* (deep copy). Defaults to `false`.
340341
* @returns {Object} Reference to `dst`.
341342
*/
342343
function extend(dst) {
343344
var h = dst.$$hashKey;
344345
var argsLength = arguments.length;
345-
var isDeep = (argsLength >= 3) && (arguments[argsLength - 1] === true);
346+
var isDeep = false;
347+
if (argsLength >= 3) {
348+
var maybeIsDeep = arguments[argsLength - 1];
349+
// Secret code to use deep extend without adding hash keys to destination object properties!
350+
if (maybeIsDeep === true || maybeIsDeep === 0xFACECAFE) isDeep = maybeIsDeep;
351+
}
346352

347353
if (isDeep) --argsLength;
348354

349355
for (var i = 1; i < argsLength; i++) {
350356
var obj = arguments[i];
351-
if (obj) {
352-
var keys = Object.keys(obj);
353-
for (var j = 0, jj = keys.length; j < jj; j++) {
354-
var key = keys[j];
355-
var src = obj[key];
356-
357-
if (isDeep && isObject(dst[key])) {
358-
src = extend(dst[key], src, true);
359-
}
357+
if (!isObject(obj) && !isFunction(obj)) continue;
358+
var keys = Object.keys(obj);
359+
for (var j = 0, jj = keys.length; j < jj; j++) {
360+
var key = keys[j];
361+
var src = obj[key];
360362

363+
if (isDeep && isObject(src)) {
364+
if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
365+
extend(dst[key], src, 0xFACECAFE);
366+
} else {
361367
dst[key] = src;
362368
}
363369
}
364370
}
365371

366-
setHashKey(dst, h);
372+
if (isDeep !== 0xFACECAFE) setHashKey(dst, h);
367373
return dst;
368374
}
369375

‎test/AngularSpec.js

+52-4
Original file line numberDiff line numberDiff line change
@@ -225,18 +225,66 @@ describe('angular', function() {
225225
});
226226

227227
it('should perform deep extend when last argument is true', function() {
228-
var src = { foo: { bar: 'foobar', age: 10, nothing: null, undef: void 0 }},
228+
var src = { foo: { bar: 'foobar' }},
229229
dst = { foo: { bazz: 'foobazz' }};
230230
extend(dst, src, true);
231231
expect(dst).toEqual({
232232
foo: {
233233
bar: 'foobar',
234234
bazz: 'foobazz',
235-
age: 10,
236-
nothing: null,
237-
undef: void 0
238235
}
239236
});
237+
expect(dst.foo.$$hashKey).toBeUndefined();
238+
});
239+
240+
241+
it('should replace primitives with objects when deep extending', function() {
242+
var dst = { foo: "bloop" };
243+
var src = { foo: { bar: { baz: "bloop" }}};
244+
extend(dst, src, true);
245+
expect(dst).toEqual({
246+
foo: {
247+
bar: {
248+
baz: "bloop"
249+
}
250+
}
251+
});
252+
});
253+
254+
255+
it('should replace null values with objects when deep extending', function() {
256+
var dst = { foo: null };
257+
var src = { foo: { bar: { baz: "bloop" }}};
258+
extend(dst, src, true);
259+
expect(dst).toEqual({
260+
foo: {
261+
bar: {
262+
baz: "bloop"
263+
}
264+
}
265+
});
266+
});
267+
268+
269+
it('should not deep extend function-valued sources when deep extending', function() {
270+
function fn() {}
271+
var dst = { foo: 1 };
272+
var src = { foo: fn };
273+
extend(dst, src, true);
274+
expect(dst).toEqual({
275+
foo: fn
276+
});
277+
});
278+
279+
280+
it('should create a new array if destination property is a non-object and source property is an array when deep-extending', function() {
281+
var dst = { foo: NaN };
282+
var src = { foo: [1,2,3] };
283+
extend(dst, src, true);
284+
expect(dst).toEqual({
285+
foo: [1,2,3]
286+
});
287+
expect(dst.foo).not.toBe(src.foo);
240288
});
241289
});
242290

0 commit comments

Comments
 (0)
This repository has been archived.