In the previous introduction, we already know that Javascript does not have block-level scope, only function-level scope.
There are also no explicit namespaces in Javascript, which means everything is defined in the global scope. Each time a variable is referenced, Javascript will traverse the entire global scope until it finds the variable. If the variable is not found after traversing the entire global scope, a ReferenceError is thrown.
Please enter image description
Implicit global variables
The two examples above produce different effects. The first one will define the variable foo in the global scope, while the second one will define the variable foo in the current scope.
We must note that not using the keyword var will have unexpected effects.
Since var is not used to define variable foo in function test, the global variable foo outside the function will be overwritten. Although it may not seem like a big problem, when there are thousands of lines of code, this can be a difficult bug to track down.
In the above example, the outer loop will stop the first time it is executed, because the variable i inside the subloop function will overwrite the outer global variable i. We only need to add a var inside the function to avoid this error, so we must not forget to add the keyword var when defining variables. Unless we really want to affect external global variables.
Local variables
Local variables in Javascript can only be generated in two ways, one is to declare through the keyword var, and the other is as a formal parameter of a function.
At this time, the variables i and foo inside the function test are local variables, and bar will overwrite the external global variable bar.
Hoisting
Javascript will hoist variable declarations, which means both var expressions and function declarations will be hoisted to the top of the scope.
Before running the above code, the var expression and the declaration of the function test will be promoted to the top, so the program will run normally and no error will be reported.
Since Javascript does not have block-level scope, this will not only elevate the var expression, but also make the if structure less intuitive.
In the above example, although it appears that if is operating on the global variable goo, in fact, because the variable goo is promoted, it is a local variable that is modified.
Without understanding the hoisting rules, you might think that the following code will throw a ReferenceError.
Of course the above code is error-free because the var expression has been promoted to the top before the code is run.
I would like to recommend @nightire Fan Ge’s blog post "Understanding JavaScript (2)", which explains the improvement very thoroughly.
Name resolution order
When trying to access a foo variable within a function scope, Javascript will look in the following order:
Whether there is a definition of var foo in the current scope.
Whether there is a foo variable in the function parameter.
Whether the function itself is named foo.
Jump to the outer domain and search from the first part.
Namespace
One of the most common problems is naming conflicts, which is caused by Javascript having only one global scope. But this problem can be solved by anonymous external functions.
The anonymous functions in the above example are considered expressions, so they will be executed.
Of course we can also call function expressions in other ways, with different structures, but the same effect.
Summary
It is recommended that you use anonymous external functions to encapsulate the code into a space. This can not only solve namespace conflicts, but also facilitate the modularization of the program.
Additionally, using global variables is not a good practice, as it is costly to maintain and prone to errors.
Namespace types, functions, variables, templates, etc. all belong to entities.
The main thing that entities have in common is that they can have names. (Also, a label can also have a name, but it is not an entity.)
The namespace scope is a general term for a type of scope, along with block scope, class scope, function prototype scope, and function scope (only valid for labels). Names declared within a namespace are in namespace scope. Global names are considered to be in implicit global namespace scope.
The role of a namespace is indeed a scope, but it is different from a simple scope. You can declare the same namespace multiple times in multiple places, but the contents cannot be redefined. They will eventually be combined into one name. Space, just like std, macro definitions everywhere