1

This works great:

var x = x || 3 //x = 3

This does not:

let y = y || 4 //Uncaught ReferenceError: y is not defined

My IDE () warns me on all usages of var, so I've been trying to avoid it (I assume this is current best practice). So what is the correct way to instantiate a variable only if it doesn't already exist?


Use Case: I am dynamically loading "widgets", which include an HTML, Javascript and CSS file. Each Javascript file has its own closure (widget = (function() {})()). I need to be able to "reload" these.

JOATMON
  • 15,576
  • 31
  • 99
  • 188
  • `var` allows redefining variable names while `let` does not. You can statically analyze whether a name exists within scope. If the `y` name is defined in scope, you'd do `y = y || 4` with no let prefix. If `y` is not defined in scope, you'd just do `let y = 4`. – vox Nov 27 '17 at 20:24
  • If this is within a function and you're passing `y` in you can set `y` as a default. [Might be a good way around that specific case.](https://jsfiddle.net/zshht4Lm/1/) – Andy Nov 27 '17 at 20:30
  • [The right-hand side `y` is in a temporal dead zone no matter the outer context.](https://stackoverflow.com/questions/33198849/what-is-the-temporal-dead-zone) I'd also consider `var x = x || 3;` immoral, even if it is syntactically valid. – vox Nov 27 '17 at 21:17

1 Answers1

1

Declare y first, then set its value in a different statement.

let y;
y = y || 4;

You can't declare with let or const multiple times, so you'll do that let declaration somewhere at the top of the scope you want it in.

Brad
  • 146,404
  • 44
  • 300
  • 476
  • This does not help. It causes `Uncaught SyntaxError: Identifier 'nearby' has already been declared` on reload – JOATMON Nov 27 '17 at 20:25
  • @RatherNotsay It does, refresh the answer, I just added a clarifying statement. – Brad Nov 27 '17 at 20:25
  • @RatherNotsay Basically, separate the declaration from the setting of its value. You can only declare it once, but you can set its value as much as you want. – Brad Nov 27 '17 at 20:26
  • I added a use case to the question. If this is my only option, I'll have to rethink how I'm doing some things... – JOATMON Nov 27 '17 at 20:27
  • @RatherNotsay Looking at your use case, I don't see what the problem is. You can declare your widget variables up top with `let`. Then load them on the fly later. If you have a dynamic set of widgets, you might just use something like `const widgets = {}`, and then to load a widget, `widgets[widgetName] = widgets[widgetName] || loadWidget(widgetName)`. – Brad Nov 27 '17 at 21:03
  • @RatherNotsay There are also existing loaders for things like this which you might look into. – Brad Nov 27 '17 at 21:03
  • To declare them "up top" I would need to know ahead of time what each widget would be named and which ones would be loaded, which sort of defeats the purpose of loading them dynamically. – JOATMON Nov 27 '17 at 21:04