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.

3 Answers 3

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.

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

7 Comments

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!
@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...
@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.
Note that this technique will not work if the caller passes for example height: 0 or title: "".
@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: "" }.
|
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');

Comments

0
var theTitle = 'Untitled';

if('title' in config && config.title != null && config.title.length > 0){
    theTitle = config.title;
}

3 Comments

!= 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) ...
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.
I agree with you. I put this code only for orientation. The above solutions are much better than mine :)

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.