Home  >  Article  >  Web Front-end  >  Javascript Study Notes - Functions (6): Scope and Namespace_Basic Knowledge

Javascript Study Notes - Functions (6): Scope and Namespace_Basic Knowledge

WBOY
WBOYOriginal
2016-05-16 16:30:461567browse

In the previous introduction, we already know that Javascript does not have block-level scope, only function-level scope.

Copy code The code is as follows:

function test() { // a scope
for(var i = 0; i < 10; i ) { // not a scope
             // count
}
console.log(i); // 10
}

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

Copy code The code is as follows:

// script A
foo = '42';
// script B
var foo = '42'

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.

Copy code The code is as follows:

// global scope
var foo = 42;
function test() {
// local scope
foo = 21;
}
test();
foo; // 21

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.

Copy code The code is as follows:

// global scope
var items = [/* some list */];
for(var i = 0; i < 10; i ) {
subLoop();
}
function subLoop() {
// scope of subLoop
for(i = 0; i < 10; i ) { // missing var statement
              // do amazing stuff!
}
}

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.

Copy code The code is as follows:

// global scope
var foo = 1;
var bar = 2;
var i = 2;
function test(i) {
// local scope of the function test
i = 5;
var foo = 3;
bar = 4;
}
test(10);

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.

Copy code The code is as follows:

bar();
var bar = function() {};
var someValue = 42;
test();
function test(data) {
If (false) {
         goo = 1;
} else {
      var goo = 2;
}
for(var i = 0; i < 100; i ) {
      var e = data[i];
}
}

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.

Copy code The code is as follows:

// var statements got moved here
var bar, someValue; // default to 'undefined'
// the function declaration got moved up too
function test(data) {
var goo, i, e; // missing block scope moves these here
If (false) {
         goo = 1;
} else {
         goo = 2;
}
for(i = 0; i < 100; i ) {
         e = data[i];
}
}
bar(); // fails with a TypeError since bar is still 'undefined'
someValue = 42; // assignments are not affected by hoisting
bar = function() {};
test();

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.

Copy code The code is as follows:

// check whether SomeImportantThing has been initialized
if (!SomeImportantThing) {
var SomeImportantThing = {};
}

Of course the above code is error-free because the var expression has been promoted to the top before the code is run.

Copy code The code is as follows:

var SomeImportantThing;
// other code might initialize SomeImportantThing here, or not
// make sure it's there
if (!SomeImportantThing) {
SomeImportantThing = {};
}

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.

Copy code The code is as follows:

(function() {
// a self contained "namespace"
window.foo = function() {
                // an exposed closure
};
})(); // execute the function immediately

The anonymous functions in the above example are considered expressions, so they will be executed.

Copy code The code is as follows:

( // evaluate the function inside the parentheses
function() {}
) // and return the function object
() // call the result of the evaluation

Of course we can also call function expressions in other ways, with different structures, but the same effect.

Copy code The code is as follows:

// A few other styles for directly invoking the
!function(){}()
function(){}()
(function(){}());
// and so on...

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

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn