2

I created a popup function and recently changed the format from this:

createPopUp('My Popup',600,200);

to this method:

createPopUp({ title: 'My Popup', width: 600, height: 200 });

I only want to use the values if they exist, so I am currently doing this:

function createPopUp(config){

  if (typeof config.title != 'undefined'){
    var theTitle = title;
  } else {
    var theTitle = 'Untitled';
  }

}

However this seems very messy so I have been looking for a more efficient way of checking for incoming parameters or setting default values and a nudge in the right direction would be much appreciated.

Community
  • 1
  • 1
valoukh
  • 541
  • 1
  • 8
  • 19

3 Answers3

3

Generally, the logical or operator is used for this:

var theTitle = config.title || 'Untitled';

Basically, the right-hand operand is an expression that will -like all expressions- resolve to a definite value. It's processedd from left to right, so if config.title is undefined, the string 'Untitled' will be the resulting value.
You can chain logical operators if you need to, too:

var someVar = obj.val || anotherObject.val || yetAnother.foo || 'bar';

Or, if all operands are objects, and you don't know which one exists:

var foo = (bar || foobar || {property: 'default: none of the objects exist').property;

The object references are grouped together, so JS will first try to resolve the variables (left to right) to an existing value, or, in the end create a new object literal with the desired propert. That reference (the result of the grouped logical-ors) is accessed, and the property .property is assigned to foo... I hope this is at least somewhat clear, if not: I'm sorry.

Caution
some properties might not be set at the instance level, or might be set, but assigned a falsy value. In that case, the logical OR is not enough, and you'll have to use either a ternary or a regular if...else:

var foo = (obj.hasOwnProperty('val') ? obj.val : 'default');//<-- uses val property, even if it's undefined, as long as it's set on the instance
//or:
var foo = 'default';
if ('val' in obj)
{//val is set, either on the instance or on its prototype-chain
    foo = obj.val
}
//as ternary:
var foo = ('val' in obj ? obj.val : 'default');
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
3

You can extend a default set of properties like this:

var defaults = {
    title: 'Untitled',
    width: 100,
    height: 100
}

function createPopUp(config)
{
    var opts = {}

    for (var k in defaults) {
        opts[k] = config[k] || defaults[k];
        // sometimes falsy values should be allowed to override defaults
        // in that case, use this instead:
        // opts[k] = typeof config[k] != 'undefined' ? config[k] : defaults[k]
    }

    // opts contains values from defaults where config doesn't have them
}

jQuery has a handy $.extend() for this purpose, but you didn't tag your post as such.

Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • Brilliant thank you, I like way you've stored the defaults in one object. I do use jQuery but I like to understand what it's doing first! – valoukh Dec 28 '12 at 14:13
  • @Jack: Just out of curiousity, but is there any reason why you're using an additional `opts` object? wouldn't `defaults[k] = config[k] || defaults[k];` work just as well? after all, the `defaults` object is constructed each time the function is invoked... – Elias Van Ootegem Dec 28 '12 at 14:17
  • @EliasVanOotegem Yes, you're right; for this example I didn't want to "pollute" the contents of `defaults` ... normally I put it outside of the function to be reused, that's why. – Ja͢ck Dec 28 '12 at 14:23
  • Note that this technique will not work if the caller passes for example `height: 0` or `title: ""`. – Raymond Chen Dec 28 '12 at 14:29
  • @RaymondChen: Well, it will work, but the result might not be what you want it to be :) – Elias Van Ootegem Dec 28 '12 at 14:31
  • @RaymondChen Yup, but considering that a zero height or empty title are pretty much useless, it would probably not be an issue ;-) but thanks. – Ja͢ck Dec 28 '12 at 14:33
  • 1
    @Jack In this particular example, perhaps, but the next person who copies this answer may have cases where `0`, `""`, or `false` is meaningful. `{ rating: 0, extraPower: false, initialContents: "" }`. – Raymond Chen Dec 28 '12 at 14:35
0
var theTitle = 'Untitled';

if('title' in config && config.title != null && config.title.length > 0){
    theTitle = config.title;
}
gezimi005
  • 381
  • 1
  • 8
  • != null to test if you give it a value or not. It's used to eliminate the case when you might put: config = {title: null, ... }; I forgot to test if it's empty or no if(config.title.length > 0) ... – gezimi005 Dec 28 '12 at 14:20
  • In that case, it's probably better to just write `&& config.title`, to check for truthy values (no emty strings, not null, not undefined, not zero, not false, ...) because if `config.title` is a number, `config.title.length` will throw an error. – Elias Van Ootegem Dec 28 '12 at 14:27
  • I agree with you. I put this code only for orientation. The above solutions are much better than mine :) – gezimi005 Dec 28 '12 at 14:34