A namespace is a separate scope for variables, functions, and types to prevent overwriting of variables and functions or preventing name conflicts. Namespacing is the practice of creating an object which encapsulates functions and variables that have the same name as those declared in the global scope.
A basic but necessary concept.
In fact, if scope didn't exist then programming itself would not be scalable at all. Let's say we're writing a program that uses some other library that's going to make what we're doing much easier. This could be anything, from a library that does advanced mathematical functions like physics or a full-on gaming engine like Unreal.
If that library declares a variable called distance
for example, how does the computer know the difference between that variable and another variable named distance
within our own script? The answer is that these two variables exist in a completely different scope. In fact when the computer compiles all the information into actual runnable code it has no idea that either of these two variables was ever called distance
in the first place. It just throws it into a completely human-unreadable address consisting of 1's and 0's machine code. As long as the complier knows the difference and puts the two variables in different places then it's all good.
Some JavaScript examples.
JavaScript is a much looser and forgiving language then something strict like C++. In JavaScript functions have access to variables globally by default, while in C++ a function only has access to exactly what we say it has access to.
Overwriting variables
What would happen if we tried to create a new string
inside of namespace()
Would that work or throw an error?
Scope hard at work here.
So now we have a variable named string
that exists globally and a variable named string
that exists only within the function. They have completely different values. This also means that the function no longer has access to the global variable because it's been overwritten.
What happens if we don't declare string
a second time?
Here we have the exact same code except I removed the variable declaration let
from the function. Now there is only one string
instead of two. The first one gets thrown to garbage collection when it gets overwritten by the second.
let
vs var
JavaScript was officially first invented in 1995 but the let
declaration didn't exist until twenty years later in 2015. They both do basically the same thing (declare a variable), but let
has a limited scope and kills off variables much sooner than var
does. It is considered good practice to use let
when the extra scope given by var
is unnecessary. However, many programmers just use var
for everything because that's the way they learned JavaScript and that's how most of the tutorials and StackOverflow answers are written.
In the above example I used let
to declare variables i
and do_something
within a for-loop. Then I tried to access these variables outside of the for-loop. This is not allowed... because apparently even loops and if-statements have their own scope in which let
cannot escape. Both these variables get destroyed by their lack of scope by the time I go to access them on the next line.
All I have to do is rewrite the let
as var
and we can see that var
breaks out of this scope to become a global variable, which I can then access outside of the loop. Again it is considered good practice to not do this unless this is specifically what the programmer was going for. For example we might make a mistake later and start accessing the variable i
thinking it's something else when it's actually 10
because of this loop. This could create a bug that takes longer to fix than if it had just thrown an error because i
was never declared in the first place due to the lack of scope. Tiny errors like this can explode into a lot of wasted time debugging things that will feel absolutely idiotic in retrospect.
Hierarchy of scope.
We would think that global variables would be at the top of the food chain in terms of scope, but that's actually not true. There is one level even above global which is the built in reserved words. These are words like let
, var
, const
, undefined
, null
, function
, etc. You aren't allowed to use these names except for their intended purpose. We can't create a function called function, nor would we want to because it would just be terrible and confusing.
- Rank 0: built-in reserved scope.
- Rank 1: global scope.
- Rank 2: functions, classes, and libraries.
- Rank 3+: nested functions, classes, and libraries.
As we can see from this test the var
declaration may be strong enough to break out of for-loop and if-statement scopes but it is not strong enough to break out of functions or classes. Even though we ran function namespace1()
and var fact
was created it got destroyed again as soon as the function popped off the stack; throwing an error when trying to access it globally after the fact. However, as I have already shown previously if we had simply declared fact
globally in the first place instead of within the function: this test would have worked as intended.
Nested functions
One advantage of putting a function inside of another function is that this child function has access to the scope of the parent. In this example namespace1()
gains access to all the variables declared in namespace2()
and is able to modify variables that it couldn't before when both were separated rank 2 functions within the global scope. The rule of thumb here being that the child tends to inherit all the traits of the parent but the children do not inherit traits from each other.
Conclusion
Scope is one of those subjects in programming that one can totally ignore as a novice; Just hack away at the code until it works like we want it to work. This is one of those topics that needs to be understood at the higher levels to reduce bugs and to create more modular products that fit together in a scalable way without creating the dreaded spaghetti factory solution that just ends up being a tangled mess that is guaranteed to break if we change anything.
If used correctly and with thoughtful intent, scope is a very powerful tool and necessary component of object oriented programing that allows us to keep building without previous builds getting in the way of what we're currently trying to achieve.
Return from Namespace & Scope to edicted's Web3 Blog