2

While reading in a JSF book, the author implements a map that serves as a namespace in which he defines some JavaScript functions.

The map is implemented like this:

if (!com) var com = {}
if (!com.example) {
    com.example= {
       myFunction: function(data) {

      // some code here

    }
  }
}

I searched to understand that syntax but didn't succeed, could someone explain to me what does !com means ? how can we check a variable if it's not already declared?

6
  • 2
    It means 'If the variable com is a falsy value, return true'. Basically, the ! is the not operator. If a value is 'falsy' (false, 0, null, '', undefined), it will turn into true. Otherwise, it is turned into false. Commented Feb 18, 2015 at 21:20
  • 1
    As a suggestion consider not reading that book. Commented Feb 18, 2015 at 21:21
  • In addition if com is undefined it will also be falsy! So if you do var com, and not set its value it will also return true Commented Feb 18, 2015 at 21:21
  • the shown code is a terrible pattern that doesn't work well for anything useful. Commented Feb 18, 2015 at 21:21
  • @IsmaelMiguel thanks for the explanation, Vohuman at that point :) ? Commented Feb 18, 2015 at 21:23

4 Answers 4

5

if (!com) checks to see if com is a falsey value. if (com) checks to see if it's a truthy value so you can see that the ! reverses the test.

In your specific code example:

if (!com) var com = {};

the code is checking to see if the com variable is defined and initialized yet. If it has not been initialized, it's value will be undefined which is a falsey value which will cause this code to then initialize it.

In Javascript, there are many falsey values and undefined is one such falsey value. The falsey values are:

null
""
false
NaN
0
undefined

See this article for more info on falsey/truthy.


One thing you have to be careful of is that if (com) or if (!com) may cause a reference error in some situations. The safest way to test if a variable has been defined and initialized is this:

if (typeof com === "undefined")

because this will not cause an error in any circumstances.

Or, a common design pattern for namespaces is this:

var com = com || {};

This will define and initialize com as a namespace object if it doesn't already exist with a truthy value.

Sign up to request clarification or add additional context in comments.

11 Comments

I saw that @dandavis said that the code is a RefError, what does that mean ?
see my answer, it's more subtle than just not falsey as my fiddle demonstrates, it involves hoisting and scope
@ToniLeigh - it depends upon the circumstance. The OP didn't mention any sort of error related to that so they were probably using the code in a context that didn't cause a referenceError. In any case, I've added more to my answer to address that issue.
@jfriend00 - I took 'how can we check a variable if it's not already declared?' to mean exactly that, as in, how does this actually work when we haven't actually done anything with that variable yet
@Tarik - yes var com = com || {}; makes sure that com either already exists and is initialized or it creates it and initializes it to an empty object. This is a very common design pattern for declaring a namespace object that is used by many different pieces of code. It does the same thing as if (com) var com = {};, but without confusion about hoisting and without putting var statements inside an if() which some people don't like to see. Example: jsfiddle.net/jfriend00/3pb68zu8
|
3

The answer here is subtler than just checking !truthy, as the OP has acknowledged by asking why we can check a value that is not assigned. Yes, the author of the example is checking whether com is falsey and if so then assigning an empty object to it, but also the fact this works depends on the use of javascript variable hoisting and the way it is scoped.

Javascript will look for all variables in it's current scope at the start of that scope and put memory aside for them, even if the value cannot be deduced. Because com is defined in the code it's initialisation is hoisted to the top of the scope it's in (global in this case) and it's already been assigned the falsey value undefined before the check is made.

In the fiddle here we can see that hoisting defines the com variable, but when execution gets to the next example where the var in the conditional is different from the tested variable - if (!comA) var comB = {} - an exception is thrown in the console.

Once assigned as an object, trying to access an undefined property on that object will also return a falsey undefined value and the next if block will also execute. Object properties are not treated like variables.

Comments

2

The first if will execute when com is a falsy value. That means undefined, false, 0, "" or maybe null.

Note that

null == false          // returns false

But

!null == !false       // returns true

Comments

0

If you haven't defined a variable, trying to access it will return undefined. Since undefined is falsy in JS, !undefined evaluates to true

2 Comments

Whoops, slip of the finger. Meant to say defined, hence the undefined
yeah, in a world of hoisting it's a crucial distinction, otherwise i'd let it slide...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.