0

So I'm reading Airbnb's JS styleguide and I don't understand what the OR operator is doing in the following example. More specifically in the Jedy constructor options || (options = {}); Is basically creating an empty object if no arguments were passed to the constructor? Therefore, the name property of the Jedi constructor would be set to 'no name'?

function Jedi(options) {
    options || (options = {});
    this.name = options.name || 'no name';
}

Jedi.prototype.getName = function getName() {
    return this.name;
};

Jedi.prototype.toString = function toString() {
    return 'Jedi - ' + this.getName();
};

PS. It seems like there are a lot shorthand ways of doing things with JS. Are there any good resources or articles explaining what these are and when it's best to use them?

  • 2
    This is idiomatic JS; its use here is exactly the same as in an `if` statement--it's just an expression, and because of short-circuiting, your assumption is correct. – Dave Newton Aug 01 '15 at 19:59
  • iirc, the airbnb style guide also recommends using `function Jedi (options = {}) {…` over what you have above (for es6). – royhowie Aug 01 '15 at 20:06
  • see [JavaScript OR (||) variable assignment explanation](http://stackoverflow.com/q/2100758/1048572), [What does the construct `x = x || y;` mean?](http://stackoverflow.com/q/2802055/1048572) and [What is "x && foo()"?](http://stackoverflow.com/q/6970346/1048572) (also [here](http://stackoverflow.com/q/12664230/1048572) and [here](http://stackoverflow.com/q/6829736/1048572)) – Bergi Aug 02 '15 at 16:23
  • @DaveNewton: the first usage is not exactly idiomatic. `if (!options) options = {};` is much clearer – Bergi Aug 02 '15 at 16:24
  • @Bergi We'll have to agree to disagree, I see the `||` version more, and because it's a pattern, I don't have to think about it. I actually think more about the `if` version, and my linter will complain about the missing braces as well. YMMV. – Dave Newton Aug 02 '15 at 19:58
  • 1
    @DaveNewton: The pattern that I'm used to is `options = options || {};`. The other is rare and weird (though I quickly understand what it means) :-) – Bergi Aug 02 '15 at 20:17
  • 1
    @Bergi Oh, yeah, I was referring to the second one, the name one--my bad. – Dave Newton Aug 02 '15 at 20:19

5 Answers5

6

The || operator takes two arguments. If the first argument is a "truthy" value, it returns the first argument; otherwise, it returns the second. It also short-circuits; that is, if the first argument is truthy it does not evaluate the second. If the second argument is an expression with side effects, this can be very significant.

The statement options || (options = {}); relies on this. If options is truthy, then the assignment expression will not be evaluated. If it is falsy, then the second expression will be evaluated.

Now, this is functional equivalent to the statement options = options || {};. In theory, that statement could be slightly slower, because it will assign options to itself rather than simply not assigning anything. However, the effect of this is negligible.

Thom Smith
  • 13,160
  • 2
  • 40
  • 78
  • That's that thing that seemed confusing. How can your have a variable assignment in the middle of a statement and not it the beginning. Is that why `(options = {})` is surrounded by parenthesis? – Diego Hernandez Aug 01 '15 at 20:07
  • 1
    @diegohernandez, assignment is an expression,which returns assigned value. Nothing special here. – Uladzislau Aug 01 '15 at 20:22
  • The second version should not be slower at all. The optimizer should be smart enough to figure it out. – Domi Sep 17 '17 at 14:19
0

Js logical operators return not true or false, but truly or falsy value itself. For example in expression x && y, if x is falsy, then it will be returned, otherwise y will be returned. So the truth table for operator is correct.

The same for ||. It's a good way for specifying function default values.

Uladzislau
  • 1,414
  • 6
  • 12
0

You will often find this code in JavaScript plugins it basically means if an object with name options does not exists create a new one

If you try to access a property on options like options.name and options does not exists then it will give you an error that options is undefined.But with this options || (options = {}) code you can always ensure that the JavaScript Object you are accessing always exists. I will check if I could provide you some links for this to read about.

This is a good supporting link How can I create an empty namespace object without overwriting another object with the same name?

Community
  • 1
  • 1
Novice
  • 458
  • 1
  • 6
  • 19
0

seems like this is a more concise way of checking that the object exists and assigning it the value of an empty object if it does not. It isn't all that clear though. A little clearer implementation would be

var options = options || {};

even better, use es2015 default parameters

function Jedi(options = {}) {
    this.name = options.name || 'no name';
}
low_ghost
  • 538
  • 1
  • 5
  • 13
0

In many (most) programming languages, at runtime unnecessary executions are optimized away. ||binary operator returns true if either of its operands evaluate to true. Since both the operands are serially evaluated, if the first one evaluates to true, the outcome of || operator is going to be true. so the second operand need not be evaluated. If the first one returns false, then second one decides what the result of || operator is going to be. this is the behavior that is being exploited here.

if options is set to non null value, it will evaluate to true. So don't execute the second operand which initializes it to empty object. on the next line if options.name is not null, then initialize it to 'no name'