views:

52

answers:

3

This is sort of what closures are meant to avoid, but I'm wondering if there's a way to a add a method to a closure. Basically I have a js file library that I'd like to augment for a specific client by adding a new method.

I have a js file called library:

var LIBRARY = (function(){
var name;
return {
setName: function(n) { name = n; }
}());

but for a new client I want to give them a new js file that will just augment LIBRARY, adding a new function:

function(first, last){
name = first + " " + last;
}

I don't want to have to modify the library js though. Is there any way to append this function to LIBRARY so that the function has the necessary access to the name variable?

+1  A: 
T.J. Crowder
A: 

Not sure exactly how you envisioned the "appending", but this works

// Base
var LIBRARY = (function(){
  var name;
  return {
      setName: function(n) { name = n; }
    , getName: function() { return name; }
  }
}());

// Extension
LIBRARY.setFullName = function( first, last )
{
  this.setName( first + " " + last );
}

// Test
LIBRARY.setFullName( 'Peter', 'Bailey' );
alert( LIBRARY.getName() );
Peter Bailey
i was hoping to be able to go directly without exposing the name variable (though the setName only exposes a setter it's not idea). might have to go this route though
statichippo
@statichippo: This really is your only option barring (again) using `eval`, which is just a can of worms.
T.J. Crowder
i'm not even considering the eval path. eval is just one letter away from evil ;)
statichippo
A: 

So I just wanted to leave a note on how I actually accomplished this because it underscores a different way of thinking about architecture in JS.

As mentioned, I wanted to be able to augment my library with client-specific functions. What I ended up doing was modifying my library to read something like:

var LIBRARY = (function(){
 var name;
 var settings;
 return {
  init: function(options){ 
    jQuery.extend(settings, options); // just merges two objects together
   }
  setName: function(n) { name = n; }
  custom: function(){
    if (!settings.custom || typeof(settings.custom == 'function'))
      return;
    name = settings.custom.apply(this, arguments);
  }
 }());

Then the client library augments my LIBRARY with a function like so:

LIBRARY.init({ custom: function(first, last) {
 return first + " " + last;
} });

so now client code can call:

LIBRARY.custom("static", "hippo");

and name will be set to "static hippo"

statichippo