3

So I admit that I'm new to javascript and that I come from a C.+ background ("Hi, I'm Bob, I'm a class-based static language user", chorus "hi Bob!").

I find that I often end up writing functions like:

function someFunc()
{
    if (arguments.length === 0 ){
       ...
    } else {
       ...
    }
}

(where there might be three such cases). Or, alternatively, I write the difference into the name:

function someFuncDefault() { ... };
function someFuncRealArg(theArg) { ... };

(Substitute "RealArg" for some semantically contentful phrase).

Is there a better pattern for this kind of thing?

2
  • Isn't this an example of method overLOADing? Commented Feb 17, 2009 at 22:35
  • 1
    I highly recommend Douglas Crockford's videos for learning javascript... they've helped me actually understand how it all fits together: video.yahoo.com/search/?p=javascript Commented Feb 17, 2009 at 22:54

7 Answers 7

3

I don't know that I would do it this way, but it seems like it might make your code mildly less unmanageable:

function someFunc() {
    switch (arguments.length) {
        case 0: noArgs();
        case 1: oneArg(arguments[0]);
        case 2: twoArgs(arguments[0], arguments[1]);
    }
    function noArgs() {
        // ...
    }
    function oneArg(a) {
        // ...
    }
    function twoArgs(a, b) {
        // ...
    }
}

Another example might be:

function someFunc(a, b) {
    if ('string' == typeof a) {
        // ...
    } else if ('number' == typeof a) {
        // ...
    }
}

And of course you can probably create something quite unmanageable by combining both examples (using conditions to determine behaviour based on number of arguments and types of arguments).

Sign up to request clarification or add additional context in comments.

7 Comments

I never knew about the argument array before. That's fantastic!
I don't see how values returned from the nested functions in your example are being handled
I don't like this... it doesn't really get around his issue of clutter in the code base, it just gives him a different way to have more methods with funny names.
@George: If you want to handle the return values, simply substitute case 0: return oneArg(arguments[0]); for what I have now.
@Akrikos: The methods with funny names are encapsulated within the defining functions and do not clutter the global namespace. If you are concerned about having a noArgs() function in every function designed this way, prefix them... someFunc_noArgs().
|
1

This is overloading, not overriding no?

Javascript is weakly typed, so method signatures and native support is out. My recommendation is to pass an extensible object as the solitary argument. Inspect and handle the existance of properties on the param object as you wish.

What advantage does this have over arguments? Well it lets you be explicit about your intentions where you call, and unambiguous about the meaning of arg1 and arg2 where you recieve, and it lets you abstract to a custom data object class you can extend functionality to.

function someFunc(params)
{
  var x = params.x || defaultX;
  var y = params.y || defaultY;

  //businesslogic
}

someFunc({x:'foo',y:'bar'});

someFunc({y:'baz'});

1 Comment

as is no, but consider this an example - typeof(params.x) != 'undefined' ? params.x : defaultX; would be more suitable
1

In Javascript, all arguments are optional.

You might try something like:

Edit (better method that doesn't break for values whose 'truthiness' is false):

function bar(arg1, arg2) {
  if(arg1 === undefined) { set default }
  if(arg2 === undefined) { set default }
  //do stuff here
}

Old method that breaks for falsey values:

function foo(arg1, arg2) {
  if(!arg1) { set default }
  if(!arg2) { set default }
  //do stuff here
}

A great place to start with javascript are Douglas Crockford's javascript lectures: http://video.yahoo.com/search/?p=javascript

3 Comments

One potential downfall to this approach is that you might want to be able to pass something that evaluates to false (such as 0) to your function. The typeof function might be safer.
true... I thought of putting that caveat, but forgot when writing :-(
hmm... it looks like I misread the question. He's already doing something similar to this.
0

Javascript lets you get really lazy with this (not quite as lazy as Python, but pretty lazy).

function someFunc(arg1, arg2)
{
  if(typeof(arg1) == "undefined") {
    arg1 = default;
  }
  ... 
}

So you don't really need to overload. Javascript won't yell at you for passing the wrong number of parameters.

3 Comments

Please fix misspelling of undefined
Is there a reason you check for 'typeof' rather than just using === the javascript reserved word undefined?
My gut tells me it's because some browser that screwed up Javascript didn't have undefined defined as a reserved word, but I don't know that for sure.
0

Everyone came close, I think that the real issue here is that in JavaScript you shouldn't change behavior based on parameters being passed in.

Since JavaScript makes all parameters optional you could follow the concise method of using this convention:

function foo(bar, baz) {
    bar = bar || defaultBar;
    baz = baz || defaultBaz;
    .
    .
    .
}

Comments

0

Personally, I prefer to write the most complex function that would be performed, and then document it in comments so that others know that they do not have to send all the arguments.

//concat(str1, str2 [,str3 [,str4 [,str5]]])
function concat(str1, str2, str3, str4, str5) {
    var str = str1 + str2;
    if(str3 != undefined)
        str += str3;
    if(str4 != undefined)
        str += str4;
    if(str5 != undefined)
        str += str5;
    return str;
}

I have also found situations where the argument order would matter in a normal function, but sometimes I would want to sent the arguments seperately (i.e. I would want to send str3 and str5 but not str4). For this, I use an object and test the known properties

//concat({str1:string, str2:string, str3:string, str4:string, str5:string})
//str3, str4, and str5 are optional
function concat(strngs) {
    var str = strngs.str1 + strngs.str2;
    if(strngs.str3 != undefined)
        str += strngs.str3;
    if(strngs.str4 != undefined)
        str += strngs.str4;
    if(strngs.str5 != undefined)
        str += strngs.str5;
    return str;
}

Comments

0

A little more comprehensive overloading mechanism is offered by bob.js:

var notify = new bob.fn.overloadFunction([ 
    { 
        condition: function(msg) { return bob.utils.isString(msg); }, 
        overload: function(msg) { 
            console.log(msg); 
        } 
    }, 
    { 
        condition: function(bSayHello) { return bob.utils.isBoolean(bSayHello); }, 
        overload: function(bSayHello, msg) { 
            msg = bSayHello ? 'Hello: ' + msg : msg; 
            console.log(msg); 
        } 
    } 
]); 

Calling the overloaded function:

notify('Simple sentence.'); 
// Output: 
// Simple sentence. 
notify(true, 'Greeting sentence.'); 
// Output: 
// Hello: Greeting sentence. 
notify(123); 
// JavaScript Error: 
// "No matching overload found." 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.