开发者

Inverse of jQuery.extend(true, …)

I'm looking to reduce storage requirements for JSON data by deltifying it against a known set of defaults. Basically, what I want is an inverse for jQuery's .extend() function, such that the following test passes for arbitrary JSON-compatible objects:

function test_delta(defaults, delta) {
    var current = $.extend(true, {}, defaults, delta);

    QUnit.same(get_delta(current, def开发者_如何学Pythonaults), delta);
}

Before I start writing my own get_delta(), is anyone aware of an existing implementation?


What you're really looking for is an object diff(erential) algorithm.

Not too difficult to write -



function diff (obj1, obj2) {
   var delta = {};

   for (var x in obj1) {
       if (obj2.hasOwnProperty(x)) {
           if (typeof obj2[x] == "object") {
               //recurse nested objects/arrays
               delta[x] = diff(obj1[x], obj2[x]);
           }
           else {
               //if obj2 doesn't match then - modified attribute
               if (obj2[x] != obj1[x]) {
                   delta[x] = obj1[x];
               }
           }        
       }
       else {
           //obj2 doesn't have this - new attribute
           delta[x] = obj1[x];
       }
   }

   return delta;
}

alert( 
  JSON.stringify(
     diff({ hello : 'world', gone : 'fishing' }, 
          { hello : 'world' })
  )
);

//outputs:
{ gone : 'fishing' }

As you can see this is a very basic implementation - you could extend this to provide a complete differential by returning additions to obj2 in a separate object.

This code isn't bug free, object protoypes and functions will be handled differently in different browsers, but it should suffice as a demonstration for data structures.


Try something like that:

jQuery.extend({
    deltaExtend: function(deep, target, defaults, delta){
        var result = jQuery.extend.apply(jQuery, arguments);
        jQuery(result).data('delta', delta);
        jQuery(result).data('defaults', defaults);
        return result;
    }
});

usage:

var result = $.deltaExtend(true, {}, defaults, delta);
$(result).data('delta') //returns delta object
$(result).data('defaults') //returns default object

It also can be tweaked to get it working for N objects, just requires a little more thinking.


I know this is a little late to be relevant to the topic starter, but you might want to have a look at the _.omit(object, *keys) function from Underscore.js. It does just that.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜