1

within a function, how to discern between a non-arg and an undefined arg?

myFunc( 'first' );

var obj = { a: 123 };
myFunc( 'first', obj.b );
_or_
myFunc( 'first', undefined )

arguments.length refers to arguments past the named arguments, so it's no help Can be solved easily with arguments.length - sorry about the brain fart!

function myFunc( a, b ) {

  // Case A: if no second arg, provide one
  // should be: if( arguments.length < 2 ) ...
  if( b === undefined ) b = anotherFunc;

  // Case B: if b is not resolved - passed but undefined, throw
  else if( b === undefined ) throw( 'INTERNAL ERROR: undefined passed' );

  // Case C: if b not a function, resolve by name
  else if( typeof b != 'function' ) { ... }

  ...
}

What is the correct way to capture Case A and Case B in myFunc?

cc young
  • 18,939
  • 31
  • 90
  • 148
  • When would you ever pass `undefined` as a function argument? That is not usual, is it? – Pekka Oct 13 '11 at 07:12
  • this is a library. if someone mis-uses it, eg, passing an undefined, wish to raise an error. – cc young Oct 13 '11 at 07:14
  • 4
    Why do you say `arguments.length` is no help? See http://jsfiddle.net/4V7FY/ – Ray Toal Oct 13 '11 at 07:15
  • I'm not sure it's worth cluttering a library with code checking for this occasion. IMO. Why not use the same behaviour in that case like when no argument is passed and be done with it? – Pekka Oct 13 '11 at 07:16
  • 1
    Would it not be better to just handle `undefined` with your Case A (or one of your cases, anyway) every time, regardless of *how* the argument came to be `undefined`? – James Allardice Oct 13 '11 at 07:16
  • It will throw an error automatically I guess because it will fail somewhere in your code.... a solution depends on which are acceptable values for `b`. – Felix Kling Oct 13 '11 at 07:16
  • @Ray Toal - Because I was _brain dead_! Was reading doc on **Dart**, where (as I recall - need to check) `arguments` was those _after_ the named args - _mea culpa_ – cc young Oct 13 '11 at 07:17
  • 2
    In fact, passing undefined should be treated in the same way as not passing the argument, you shouldn't make a difference between the 2. – deviousdodo Oct 13 '11 at 07:17
  • @draevor - respectfully disagree. _not_ passing a second arg is asking for the function to provide the default. passing an `undefined` second arg is simply a bug. – cc young Oct 13 '11 at 07:21
  • @ccyoung Ah, okay, I see. Well I was going to turn that comment into an answer but (1) Yoshi just did, and (2) I gotta say I agree with draevor that you actually _should not_ try to distinguish this case because the semantics of JavaScript say that when no argument is passed to a parameter, that parameter gets the value `undefined`, which _should be treated the same as having `undefined` explicitly passed_ IMHO. :) Granted passing `undefined` explicitly is ugly, but maybe the caller is expecting to take advantage of these JavaScript semantics? Then again, `arguments` exists.... – Ray Toal Oct 13 '11 at 07:22

2 Answers2

3

Try something like:

function myFunc() {
  var a, b;

  if (arguments.length === 1) {
    a = arguments[0];
    console.log('no b passed');
  }
  else if (arguments.length > 1) {
    a = arguments[0];
    b = arguments[1];
    if (b === undefined) {
      console.log('undefined passed as parameter');
    }
  }

  console.log(a, b);
}

myFunc(1);
myFunc(1, undefined);
Yoshi
  • 54,081
  • 14
  • 89
  • 103
1

I believe there's no cross-browser compatible way to do exactly what you wish. Moreover, I think that a function that changes its behavior when undefined is passed explicitly (vs. not passed at all) is confusing. That said, your overall target can be achieved by slightly changing the protocol.

Let's examine how you want my_func to be used:

my_func(1) // case A
my_func(1, undefined) // case B
my_func(1, {}.b) // case B
my_func(1, "blah") // case C

See my point? Case A can happen only if the caller passes a single argument.

Thus, if you separate my_func() into two functions: my_funcA, taking a single argument, and my_funcBC, taking two arguments, you will be able to implement your logic correctly.

The only change that this inflicts, on the caller of the function, is that if the caller passes a single argument he needs to call my_funcA(). In all other casses, my_funcBC() should be called.

 function my_funcA(a) {
   my_funcBC(a, anotherFunc);
 }

 function my_funcBC(a, b) {
   if (b === undefined) 
     throw( 'INTERNAL ERROR: undefined passed' );

   if (typeof b != 'function') { ... }     
   ...
 }
pimvdb
  • 151,816
  • 78
  • 307
  • 352
Itay Maman
  • 30,277
  • 10
  • 88
  • 118