A few weeks ago, while analyzing some of the CSS code for jQuery, I noticed a call to the swap() function. After looking through the definition of the function and reading the reason for using it in the documentation, I realized that this function might be pretty useful for others.

In jQuery, the swap function is used to temporarily change multiple values of an object, run a callback function, and then restore those values after the callback is complete. This becomes useful when you need to change the values of properties of an element in order to test how the element acts under those circumstances.

Here is a definition for a modified version of this function:


// Temporarily puts the properties of tempProps into obj,
// executes fnCallback, results obj to its previous state,
// and then returns what was returned by the callback.
var swap = (function() {
  var hasOwnProperty = Object.prototype.hasOwnProperty;
  
  return function(obj, tempProps, fnCallback) {
    // Get the array of all the property names that belong to obj.
    var keys = [];
    for(var key in tempProps) {
      if(hasOwnProperty.call(tempProps, key)) {
        keys.push(key);
      }
    }
    
    // Temporarily store the properties of tempProps in obj.
    var oldProps = {};
    for(var key, len = keys.length, i = 0; i < len; i++) {
      key = keys[i];
      oldProps[key] = obj[key];
      obj[key] = tempProps[key];
    }
    
    var error, errorSet;
    try {
      // Store what is returned from fnCallback in ret.
      var ret = fnCallback.call(obj ,obj, oldProps);
    }
    catch(e) {
      // Store the error that was thrown.
      error = e;
      
      // Note that the error was set.
      errorSet = 1;
    }
    
    // Go throw and restore the previous values of obj.
    while(--i >= 0) {
      key = keys[i];
      obj[key] = oldProps[key];
    }
    
    // If the error was set, throw it now that the properties of obj have
    // been successfully restored.
    if(errorSet) {
      throw error;
    }
    
    // If everything went smoothly, return whatever was returned from
    // fnCallback.
    return ret;
  };
})();

This function has been modified to make sure that if an error is thrown by fnCallback, the old properties for obj will be restored before the error is thrown.

Right now, I can’t think of many other uses for this function, but perhaps by bringing more attention to this function’s existence, this post will help others think of cool ways to take advantage of this function. 8)

Categories: BlogJavaScriptJScript

Leave a Reply

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