views:

676

answers:

4

I'm wondering if there's a better way to add dynamic methods to an existing object. Basically, I am trying to assemble new methods dynamically and then append them to an existing function.

This demo code works.

builder = function(fn, methods){

 //method builder
 for(p in methods){
  method = 'fn.' + p + '=' + methods[p];
  eval(method);
 }

 return fn;
}
test = {}
test = builder(test, {'one':'function(){ alert("one"); }','two':'function(){ alert("two"); }'} );

test.one();
test.two();
+1  A: 

You don't need to eval them each time.

You can create existing Function objects, then assign them as properties to your objects.

var methods = {
  'increment': function() { this.value++; },
  'display' : function() { alert(this.value); }
};

functions addMethods(object, methods) {
  for (var name in methods) {
    object[name] = methods[name];
  }
};

var obj = { value: 3 };
addMethods(obj, methods);
obj.display();  // "3"
obj.increment();
obj.display();  // "4"

Of course, the canonical, object-oriented way is to use constructors and prototypes (but this isn't really dynamic in that each object you construct will have the same methods):

function MyObj(value) {
  this.value = value;
};
MyObj.prototype.increment = function() {
  this.value++;
};
MyObj.prototype.display = function() {
  alert(this.value);
}
var obj = new MyObj(3);
obj.display();  // "3"
obj.increment();
obj.display();  // "4"
levik
A: 

Do you have to build the methods from a string? If not there are plenty of ways including adding the methods to an object prototype or the object definition directly. Most of all the common javascript libraries have methods for defining objects/methods on existing or creating "namespaces". Check out YUI/Prototype/jQuery etc for examples of how they implement.

Otherwise if you have to build from a string then evaling may be the best method for dynamically adding methods to an object definition.

Quintin Robinson
A: 

Nothing is preventing you from using the object literal syntax to do that.

var obj = {
  one: function() {
    //...
  },
  two: function() {
    //...
  }
}

And objects, are dictionaries, right? They are not as you say, statically typed. This means that it's perfectly fine to add new properties i.e. functions to any object at any time. How you do it, well, that a matter of great opinion, but JavaScript falls in the category of prototype-based programming languages and as such you should really take a look at this. I gives some good insight into what that entails and how to do it.

John Leidegren
A: 

Your example could be accomplished without strings:

builder = function(fn, methods){

        //method builder
        for(p in methods){
                fn[p] = methods[p];
        }

        return fn;
}
test = {}
test = builder(test, {'one': function(){ alert("one"); },'two':function(){ alert("two"); }} );

test.one();
test.two();

I'm not sure how you are assembling these methods, but avoid using strings if you can. There is probably a better way.

Zach