2

I am trying to get to grips with es6 classes and I seem to be unable to pass a boolean value to a constructor.

In the following code

export default class site_alert {
  constructor(options) {
    this.message = options.message || 'default cookie message';
    this.autoDisplay = options.autoDisplay || true;
    console.log(this.autoDisplay);
  }
}

var sitemessage = new site_alert({
  message:"Some string",
  autoDisplay: false
});

autoDisplay is always true, it takes the default value regardless of whats being passed to it when I create an instance of the class.

If I change autoDisplay to be a string it works fine.

Are you unable to pass booleans to the constructor like this?

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
davidjh
  • 387
  • 1
  • 7
  • 13
  • That's because `||` is an or comparator. You've effectively said `options.autoDisplay OR true`, which always resolves to `true`, regardless of `options.autoDisplay` value. – Hopeful Llama Jun 21 '16 at 11:13
  • Even if you pass the value as false, it will end up in the constructor as: this.autoDisplay = false || true, which is indeed true. – Adrian Fâciu Jun 21 '16 at 11:13

1 Answers1

5

false || true is always true. || is evaluated like this:

  • Evaluate the left-hand side
  • If the left-hand side is truthy, that's the result
  • Otherwise, evaluate the right-hand side and make that the reslt

So || isn't the way to do this. You'd also have trouble if you wanted to be able to supply any other falsy value, like 0, "", null, etc.

You could use typeof options.autoDisplay === "undefined" or "autoDisplay" in options (more in this question and its answers)

this.autoDisplay = typeof options.autoDisplay === "undefined" ? true : options.autoDisplay;

...but you're using ES2015 ("ES6"), so you can avoid all that boilerplate by using default arguments and argument destructuring:

constructor({message = 'default cookie message', autoDisplay = true} = {}) {
    this.message = message;
    this.autoDisplay = autoDisplay;
    console.log(this.message, "|", this.autoDisplay);
}

Live Example:

class site_alert {
  constructor({message = 'default cookie message', autoDisplay = true} = {}) {
    this.message = message;
    this.autoDisplay = autoDisplay;
    console.log(this.message, "|", this.autoDisplay);
  }
}
new site_alert();
new site_alert({autoDisplay:false});
new site_alert({message:"custom message"});

Note how in our function code, we don't even have options anymore; the arguments are destructured from the options object for us when the function is called.

Let's look at that declaration:

{message = 'default cookie message', autoDisplay = true} = {}

The {message = 'default cookie message', autoDisplay = true} part says:

  • The first (only, in our case) argument will be an object we want destructured (thanks to the {} around it)
  • If there's no message property on it, default to 'default cookie message'
  • If there's no 'autoDisplay' property on it, default to true

...and the = {} part says: If the argument isn't given, default to a blank object (after which the two defaults above will kick in).


Side note: The overwhelming convention in JavaScript is that constructor functions (classes) are written with a capital first letter (and usually in CappedCamelCase), so SiteAlert rather than site_alert. You don't have to follow convention, but just flagging it up if you didn't know.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875