Javascript: better way to add dynamic methods?

30,741

Solution 1

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); }
};

function 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"

The canonical, object-oriented way however, 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"

Solution 2

mhmh - I may be a bit late, but anyway:

new Function(argName1,...,argNameN, body)

for example:

x = new Function("y","return y*5");
x(3)

not much better than eval, though. (it's a pity, but strings are used as code-description, not something more structured as in LISP)

Solution 3

If you need an object dynamically based on specific types... For instance:

var logTypes = ["fatal", "error", "warning", "info", "trace", "debug", "profile"];

Then you can keep a reference of the "this" object output and use it inside the methods.

function CustomLogger () {

   var outter = this;

   // creating the logger methods for all the log types and levels
   _.each(logTypes, function (logType) {
        outter[logType] = function (msg) {
           console.log("[%s] %s", logType, msg);
        };
   });
}

That way, you can get the new dynamic methods...

var logger = new CustomLogger();
logger.info("Super cool!");

This will output the following:

"[info] Super cool!"

Solution 4

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.

Share:
30,741
Geuis
Author by

Geuis

Updated on August 21, 2020

Comments

  • Geuis
    Geuis almost 4 years

    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();