In my endeavour to write clean Javascript code as a beginner, I was recently reading this article about namespacing in JavaScript when I stumbled upon this paragraph:
The code at the very top of the next sample demonstrates the different ways in which you can check to see if a variable (object namespace) already exists before defining it. You'll commonly see developers using Option 1, however Options 3 and 5 may be considered more thorough and Option 4 is considered a good best-practice.
// This doesn't check for existence of 'myApplication' in // the global namespace. Bad practice as you can easily // clobber an existing variable/namespace with the same name var myApplication = {}; /* The following options *do* check for variable/namespace existence. If already defined, we use that instance, otherwise we assign a new object literal to myApplication. Option 1: var myApplication = myApplication || {}; Option 2 if(!MyApplication) MyApplication = {}; Option 3: var myApplication = myApplication = myApplication || {} Option 4: myApplication || (myApplication = {}); Option 5: var myApplication = myApplication === undefined ? {} : myApplication; */
Option 1 is certainly the one I have seen used most of the time, and I understand it well.
Option 2 is fine but seems to lack a var myApplication
beforehand or a if(!window.myApplication)
otherwise if myApplication
is not in the global scope the condition if(!myApplication)
would throw an error, wouldn't it?
Option 3 is the one I have trouble with: my understanding is that the myApplication = myApplication
is executed first, with myApplication
in the global scope (due to the var
at the begining). My problem is that I can't think of a case where this option does anything more than option 1.
Option 4 in my eyes would have been better written window.myApplication || (myApplication = {})
to avoid throwing an error if myApplication
is not in the global scope.
Option 5 is excluding the false-y values other than undefined
but is it a good idea? If myApplication
is say an empty string, the rest of the code is likely to fail, isn't it?
Would someone be able to shed some light on the differences between the different options and in particular explain why option 3 is described as more thorough?
var is the keyword that tells JavaScript you're declaring a variable. x is the name of that variable. = is the operator that tells JavaScript a value is coming up next. 100 is the value for the variable to store.
The var statement declares a function-scoped or globally-scoped variable, optionally initializing it to a value.
Variables declared with the var keyword are always function-scoped, meaning they recognize functions as having a separate scope. This locally-scoped variable is therefore not accessible from the global scope.
Basically, var declares a variable and you can also assign to it at the same time. Without var , it's assigning to the variable. Assigning will either assign to an existing variable or create a global variable of that name then assign to it.
If the article claims Option 3 is "more thorough," it's incorrect. There's no point to the middle of that assignment chain at all.
Would someone be able to shed some light on the differences between the different options and in particular explain why option 3 is described as more thorough?
First, a caveat: Here in 2018, you probably don't want to use any of these. Instead, use proper modules, either via one of the various module definition syntaxes (AMD, CommonJS, RequireJS) with a relevant tool, or via ES2015+ modules with import
and export
(and probably a relevant tool such as Babel and perhaps Webpack or Browserify, although current versions of Chrome, Safari, and Edge support modules natively, and Firefox does as well currently behind a flag).
Why is
var x = x = x || {}
more thorough thanvar x = x || {}
?
It isn't.
Option 2 is fine but seems to lack a
var myApplication
beforehand or aif(!window.myApplication)
otherwise ifmyApplication
is not in the global scope the conditionif(!myApplication)
would throw an error, wouldn't it?
Yes. (Assuming that production occurs at global scope. if it's not at a global scope and there's an in-scope myApplication
anywhere in the current scope chain, it won't throw because myApplication
won't be an unresolved symbol.)
Option 3 is the one I have trouble with: my understanding is that the
myApplication = myApplication
is executed first, withmyApplication
in the global scope (due to thevar
at the begining). My problem is that I can't think of a case where this option does anything more than option 1.
No, if you have
var myApplication = myApplication = myApplication || {}
this is the order in which things happen:
var myApplication
creates the global if it doesn't already exist, leaves it untouched if it doesmyApplication || {}
is evaluated and takes either the value in myApplication
(if it's truthy) or {}
(if not); let's call that value1
myApplication = value1
(the one in the middle) is performed, and the result is value1
myApplication = value1
(the one on the left) is performed again for no good reasonOption 4 in my eyes would have been better written
window.myApplication || (myApplication = {})
to avoid throwing an error ifmyApplication
is not in the global scope.
Indeed.
Option 5 is excluding the false-y values other than
undefined
but is it a good idea? IfmyApplication
is say an empty string, the rest of the code is likely to fail, isn't it?
Yes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With