Hao's Blog Code and Stuff

fuse.js - Merge JavaScript Objects

I am working on a simple multi-player browser game. I used node.js as game server, and socket.io to establish real-time messaging between the players. Naturally, there is a room management module keeping track of all active game sessions, and synchronizing states among all involved parties. As part of the module, I keep game state and player states in the room data structure, which I constantly update when the game or player is emitting an event. With that, I found myself writing endless adapter codes to parse events and updating states, which made me wonder if there is an easier way to do this…

Of course there is. One of the solution is jQuery’s extend() function. As the documentation states:

jQuery.extend( target [, object1 ] [, objectN ] )

Description: Merge the contents of two or more objects together into the first object.

which, will do the trick just fine. However, I want to add some other features into it in case I need them, such as calculate the delta (difference) of the merge. After some digging around StackOverflow, it seems going through all the properties of the object and update each individually is a popular solution. So I took the idea a step further to incorporate the updating of nested objects, and here is fuse.js:

(function () {

    /**
     * Wrapper function
     * @param target: target object
     * @param delta: delta object
     * @return 
     */
    module.exports = function (target, delta) {
        return f(target, delta);
    };

    /**
     * Recursive call function
     * @param target: target object
     * @param delta: delta object
     * @return 
     */
    function f (target, delta) {
        // Base case:
        // if obj is not object/array, just return itself
        if (typeof delta !== 'object') {
            return delta;
        }
        // General case:
        // go through all key/index(s) in object/array
        for (var key in delta) {
            if (target.hasOwnProperty(key)) {
                // update
                target[key] = f(target[key], delta[key]);
            } else {
                // insert
                target[key] = delta[key];
            }
        }
        return target;
    }

})();

It’s an extremely simple snippet which is quite self-explanatory. However, there is one thing requires clarification: in this script, an array is treated the same as an object, so if you are updating say [1,2,3,4] with [7,8], the end result will be [7,8,3,4], because these elements share the same index, which effectively is key in the snippet.

Future work: I will keep adding features to this module as I mentioned before, hopefully it will be somewhat useful in the future.


Comments