As I was thinking about the swap() function that jQuery uses internally, I thought some people may also find a backup() function and restore() function useful. For instance, you may get tired of worrying about using the var keyword inside of a function in order to prevent the variable from being defined on the global scope. If this is the case, you could use the backup() function before defining any global variables, pollute the global scope as much as you want, and then use the restore() function to set the global object back to the way it was. Before we check out an example of doing this, let’s take a look at the definition for these two new functions:

// Backup & Restore Functions - By Chris West - MIT Licensed
(function() {
  var arrBackups = [], arrRefs = [];

  // Defines the backup function in the global scope.
  backup = function(obj) {
    // The object that will keep track of what was in obj when it was passed
    // in.
    var objBackup = {};
    for(var key in obj) {
      try{ objBackup[key] = obj[key]; }catch(e){}
    }

    // Add the backup to the array of backups.
    arrBackups.push(objBackup);

    // Add a reference to obj to the array of references.
    arrRefs.push(obj);

    // Return a backup ID.
    return arrBackups.length - 1;
  };

  restore = function(backupID, obj, fnFilter, deleteNewbies) {
    // If there is nothing at the specified backup ID, throw an error.
    if(!(backupID in arrBackups)) {
      throw new Error("Unknown Backup ID");
    }

    // Reference the backup object.
    var objBackup = arrBackups[backupID];

    // If an object to restore to wasn't specified, simply use the object that
    // was originally backed up.
    if(obj == null) {
      obj = arrRefs[backupID];
    }

    // If the filter function was specified, use it to identify which
    // properties should be restored.
    if(fnFilter) {
      for(var key in objBackup) {
        if(fnFilter(key, objBackup[key], obj[key])) {
          try{ obj[key] = objBackup[key]; }catch(e){}
        }
      }
    }
    // If no filter function was specified, simply restore all properties.
    else {
      for(var key in objBackup) {
        try{ obj[key] = objBackup[key]; }catch(e){}
      }
    }

    // If new properties that were created since the backup are to be deleted,
    // make it so.
    if(deleteNewbies) {
      for(var key in obj) {
        if(!(key in objBackup)) {
          delete obj[key];
        }
      }
    }
    return obj;
  };
})();

The documentation pretty much explains what occurs when backing up and restoring objects. One thing to keep in mind is the fact that if the properties are objects whose states change, their state will not be restored. The only things that are restored are the references to the objects and primitives.

Now it is time to play around with the global scope by defining a lot of global variables after running backup, and then restoring the window object. Here is the code:

// Define an object before backup.
jQuery = {awesome:true};

// Store the backup ID.
backupID = backup(window);

// Create some global variables.
two = 2;
sixty_four = 64;
two_to_sixty_four = Math.pow(two, sixty_four);
reNumber = /^\d+$/;

// Delete the reference to the fake jQuery object.
delete jQuery;

// Show the status of the global window object.
alert([
  '"backupID in window == ' + ("backupID" in window),
  '"two" in window == ' + ("two" in window),
  '"sixty_four" in window == ' + ("sixty_four" in window),
  '"two_to_sixty_four" in window == ' + ("two_to_sixty_four" in window),
  '"reNumber" in window == ' + ("reNumber" in window),
  '"jQuery" in window == ' + ("jQuery" in window)
].join("\n"));

// Restore the window object from the specified backup.
restore(
  backupID /*backup ID*/,
  null /*other object to restore to*/,
  function(key){ return key != "location"; } /*filter function*/,
  true /*remove newly created properties*/
);

// Show the status of the global window object.
alert([
  '"backupID in window == ' + ("backupID" in window),
  '"two" in window == ' + ("two" in window),
  '"sixty_four" in window == ' + ("sixty_four" in window),
  '"two_to_sixty_four" in window == ' + ("two_to_sixty_four" in window),
  '"reNumber" in window == ' + ("reNumber" in window),
  '"jQuery" in window == ' + ("jQuery" in window)
].join("\n"));

If you run the above code in a blank web page you will see that backupID, two, sixty_four, two_to_sixty_four, and reNumber will be defined but then will be deleted after the restore. On the other hand, since jQuery was defined before the backup, even though it is deleted, once window is restored, jQuery is once again defined.

Categories: BlogJavaScriptJScript

Leave a Reply

Your email address will not be published. Required fields are marked *