diff --git a/src/zepto.js b/src/zepto.js index ae9858f40..a29a4d469 100644 --- a/src/zepto.js +++ b/src/zepto.js @@ -177,14 +177,24 @@ var Zepto = (function() { return zepto.init(selector, context) } + function extend(target, source, deep) { + for (key in source) + if (deep && isPlainObject(source[key])) { + if (!isPlainObject(target[key])) target[key] = {} + extend(target[key], source[key], deep) + } + else if (source[key] !== undefined) target[key] = source[key] + } + // Copy all but undefined properties from one or more // objects to the `target` object. $.extend = function(target){ - slice.call(arguments, 1).forEach(function(source) { - for (key in source) - if (source[key] !== undefined) - target[key] = source[key] - }) + var deep, args = slice.call(arguments, 1) + if (typeof target == 'boolean') { + deep = target + target = args.shift() + } + args.forEach(function(arg){ extend(target, arg, deep) }) return target } diff --git a/test/zepto.html b/test/zepto.html index d86bf96a9..08ecd267e 100644 --- a/test/zepto.html +++ b/test/zepto.html @@ -368,6 +368,39 @@

Zepto DOM unit tests

// undefined values are not copied over t.assertSame({a:1}, $.extend({a:1}, {b:undefined})) + + // shallow by default + obj = $.extend({ a:{b:"c"} }, { a:{d:"e"} }) + t.assertSame({d:"e"}, obj.a) + }, + + testExtendDeep: function(t){ + var obj = { a:{b:"c", x:{y:"z"}} } + $.extend(true, obj, { a:{d:"e"} }, { a:{b:"B", f:"g", x:{q:"x"}} }) + + t.assertEqual('a', Object.keys(obj).join(',')) + t.assertEqual('b,d,f,x', Object.keys(obj.a).sort().join(',')) + t.assertEqual('B', obj.a.b) + t.assertEqual('e', obj.a.d) + t.assertEqual('g', obj.a.f) + t.assertEqual('z', obj.a.x.y) + t.assertEqual('x', obj.a.x.q) + + // creates non-existing keys on target object + obj = {} + $.extend(true, obj, { a:{b:"c"} }) + t.assertEqual('a', Object.keys(obj).join(',')) + t.assertEqual('c', obj.a.b) + + // skips iterating over DOM elements + obj = {} + var dom = $('#some_element').get(0) + $.extend(true, obj, { element: dom }) + t.assertIdentical(dom, obj.element) + + // can override DOM element + $.extend(true, obj, { element:{a:'b'} }) + t.assertEqual('b', obj.element.a) }, testExtensionAPI: function(t) {