Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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, defaults), delta);
}

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

like image 574
Ben Blank Avatar asked Aug 04 '10 21:08

Ben Blank


People also ask

What does jQuery extend do?

jQuery | extend() method This extend() Method in jQuery is used to merge the contents of two or more objects together into the first object.

What is extend js?

The extends keyword is used in class declarations or class expressions to create a class that is a child of another class.

How do you extend an object in JavaScript?

The extends keyword can be used to extend the objects as well as classes in JavaScript. It is usually used to create a class which is child of another class. Syntax: class childclass extends parentclass {...}


2 Answers

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.

like image 160
Marcus Pope Avatar answered Oct 05 '22 07:10

Marcus Pope


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.

like image 37
Amjad Masad Avatar answered Oct 05 '22 06:10

Amjad Masad