6

I often use var options = options || {} as way to default to an empty object. It's often used to initialize an option object in case it's not passed in the parameter of a function call.

The thing is I've read in several places (blog posts, source code) that options || (options = {}) better express the developer's intent. Can someone elaborate on it? I don't see the functional difference between the two, so there's something I must be missing here.

--- edit

I saw in Backbone.js source code in several places, like https://github.com/documentcloud/backbone/blob/0.9.2/backbone.js#L273

I think I saw it too in jQuery's source code too. And in the multiple Js writing style guides that flourished.

--- edit 2 code example :

var func = function(param, options) {
   // How I do it
   var options = options || {};
   // How I should do it in the "same" way
   options = options || {};
   // The "other" way
   options || (options = {});

}
Usman Ismail
  • 17,999
  • 14
  • 83
  • 165
DjebbZ
  • 1,594
  • 1
  • 18
  • 34

7 Answers7

5

There's no real difference, assuming you meant:

function fn(options) {
    // type a
    options = options || {};

    // type b
    options || (options = {});
}

Mostly a matter of preference, I think (a) is a whole lot clearer, I don't like the statement with no assignment on the LHS.

Evan Trimboli
  • 29,900
  • 6
  • 45
  • 66
4

There isn't a functional difference.

The second construct just (subjectively) looks like it does what it does more than the first construct.

The counter argument is that the first construct is a common pattern, so is more easily recognised to do what it does.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • Agreed, to someone who is not too close with JavaScript, the first notation would look more understandable. – naivists Nov 19 '12 at 12:18
3

They should do the same thing, but there is a better way.

Theoretically the second, assigning only if the value is falsy, could eliminate an assignment and be faster. Indeed in a jsperf we see it is (12%).

In fact the explicit if statement is just as fast as the condition-then-assign:

if(!options)
    options = {};

Try the test on your browser/machine.

I think the explicit if is the most clear, and has no penalty.

Edit:

If you are expecting an object to be passed in to a function, then I think the better test is:

if(typeof options !== 'object') 
    options = {};

This will ensure that you have an object afterwards, even if it is empty. Any other test (for undefined, or falsiness) will permit a truthy non-object through like a non-zero number or a non-empty string. As the jsperf shows, however, this is ~15% slower. Since you only do this on entry to a function which will be processing objects, I would argue that is a worthwhile tradeoff, and is barely slower that the always-assign.

Phil H
  • 19,928
  • 7
  • 68
  • 105
2

There is a functional difference: one uses var and the other does not. If there is any possibility that the options variable does not exist in the current scope, it is much better to use var rather than risk options leaking out into outer scopes implicitly.

If options is guaranteed to exist (for example, within a function whose parameters include options), the two statements are functionally identical so the problem reduces to the relative stylistic merits of options = options || {} versus options || (options = {}). Personally I see little difference: both require the same knowledge of how JavaScript's || operator works, so once you remove that factor from the equation, I would probably favour options = options || {} as being slightly more readable by virtue of being shorter and simpler. The developer's intention seems equally clear to me in either case.

Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • Yes of course. I forgot to add a bit of code to make it explicit, where the `options` variable actually exists in the function paramaters. So while your point is very valid, it has no impact in my case. – DjebbZ Nov 19 '12 at 12:49
1

There is indeed no functional difference between the two, even though their mechanics are not identical.

The first form sets the local variable options to be equal to the parameter options or to an empty object if the argument has a falsy value (e.g. if it has not been provided).

The second form evaluates to the value of the parameter options (if it's not falsy), otherwise it evaluates to the result of the assignment of the empty object to that parameter. So the difference from the first form is that if options is truthy, no assignment is performed.

Personally I consider the second form to be a less readable version of

if(!options) {
    options = {};
}

to which is identical in both function and mechanics.

Jon
  • 428,835
  • 81
  • 738
  • 806
1

There is no functional difference, the idea is that options || (options = {}); is closer to what the programmer really want to express, which is actually:

if (typeof options == "undefined") {
  options = {};
}

The || operator is used to make shorter code, not clearer code.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • There's quite a gap between falsy and undefined, so if you really want to override undefined, do that explicitly. – Phil H Nov 19 '12 at 12:23
  • @PhilH: Yes, there is a gap, but neither version of the codes is equipped to handle all values in the gap anyway. Both versions lets some values that are useless in this context, like for example `true`, slip through and let the rest of the code choke on them. – Guffa Nov 19 '12 at 12:30
  • Very true. This is one of the downsides of a dynamically typed language. – Phil H Nov 19 '12 at 12:38
  • I suppose the better version, assuming an object is expected, is to test `if(typeof options !== 'object') options = {};`, which should be more robust. – Phil H Nov 19 '12 at 12:42
0

Definitely subjective, but I wouldn't use the second.

Reason: I feel that assignments in expressions anywhere deeper than the top-level = obfuscation.

Some C programmers like that (I used to, once), they do things like extra parens to make the assignment more clear... by making the whole expression look unfamiliar. Why bother if you can just be straightforward?

The most clear would probably be:

if (!options) options = {};
Kos
  • 70,399
  • 25
  • 169
  • 233