Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Let's say I have an object like this:

function Foo() {
  this.parser = new DataParser();
};

Within Foo I have a method that does something like this:

Foo.prototype.getResponse = function(message, callback) {
  var payload = {data: message, type: 'normal'};
  var response = this.parser.parse(payload, function(data){
    callback(data);
  });
}

Now, let's say that somewhere else I need to call foo.getResponse(). Most of the time I want it to run just like this, but on occasion I need the format of the payload to be slightly different - let's say I need to specify a different type.

Would it be better to make a different method for this slightly different kind of request, like so...

Foo.prototype.getSimilarResponse = function(message, callback) {
  var payload = {data: message, type: 'other'};
  var response = this.parser.parse(payload, function(data){
    callback(data);
  });
}

... or to take an option on getReponse, like so...

Foo.prototype.getSimilarResponse = function(message, type, callback) {
  var payload = {data: message, type: type};
  var response = this.parser.parse(payload, function(data){
    callback(data);
  });
}

... or to do something else entirely?

Using a type option in the example above is a lot more DRY, but I don't like the way it requires the caller to know about payload type, which is really the concern of Foo and doesn't need to be exposed anywhere else.

How would you recommend approaching a situation like the above?

share|improve this question
1  
Every class, module or whatever has a documentation, and when a user needs to use it, he just reads that documentation. Here I see the same, I agree with the answer below, It's better to have a customizable method that a lot of functions with small changes. –  ecampver Mar 17 '13 at 4:37
    
@e.campver Thanks for the insight, I appreciate it. –  Andrew Mar 18 '13 at 16:03

2 Answers 2

up vote 7 down vote accepted

I would recommend to pass the type argument 'optionally' so you'd get a function like:

Foo.prototype.getSimilarResponse = function(message, type, callback) {
  if (typeof(type) === 'function') {
    callback = type;
    type = 'normal';
  }

  var payload = {data: message, type: type};
  var response = this.parser.parse(payload, function(data){
    callback(data);
  });
}

That way, your code is DRY and you don't have to worry about the type if you don't want/need to.

share|improve this answer
    
This is what I'd probably do, also, The question doesn't have much to do with OOP. This is also pretty much how every node.js api works. –  Benjamin Gruenbaum Mar 16 '13 at 21:48
    
Untyped, variable-length args certainly has impact on a lot of the stuff we don't have as much use for in JS OOP. No need to redefine methods for arg overloads. Circumvents inheritance as the primary approach to variation on a theme. It's arguably one of the main reasons in addition to prototype and ease of compositing I've never missed classes. –  Erik Reppen Nov 15 '13 at 18:51

See also:

The Options Argument

This is very popular in the jQuery community. It's handy when you have a lot of potential for variation that might result in a ton of args which happens all the time in UI functionality.

I'm also fond of it for regular higher-level app architecture constructors. The ease of mashing objects like these together is one of the reasons inheritance is much less exclusively relied on in JS.

One of the nicer side-effects is the self-documenting factor of having an easy-to-read list of things spelling out what all the variable options are and it's really easy to add new ones without having to make changes anywhere but the function/constructor.

function Carousel(optionsIn){
    var options = {
        loopsItems:true, //first item follows last if true, or you're just stopped if false
        itemsPerScroll:'visible', //or a set number
        horizontal:true, //false is vertical
        contentInjection:false //static HTML if false, or a URL, or array of HTML
    };

    optionsIn = optionsIn || {};

    for(var x in optionsIn){
        options[x] = optionsIn[x];
    }
    //or $.extend(options, optionsIn) in jQuery land
    //behavior defined/switched on options here...

}

The Arguments Keyword

Lots of cool uses, especially for variable numbers of arguments.

function addThingsToSomeArray(){ //first arg is array, followed by any number of things
    var
        thingsLen = arguments.length-1,
        someArray = arguments[0]
    ;
    while(i--){
        someArray.unshift(arguments[i+1]);
    }
}

var someArray = [];
addThingsToSomeArray(someArray, function yay(){alert('yay');}, 'Bob', new Date(), Infinity);

Look on and become green with envy, ye of strictly-typed languages that protect you from learning a lesson once the hard way occasionally in favor of helping you to do it wrong successfully over and over again.

share|improve this answer
    
Erik, great suggestions. I wasn't familiar with the arguments keyword in JS, that's great to know! –  Andrew Nov 15 '13 at 23:08

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.