


Javascript Study Notes - Functions (6): Scope and Namespace_Basic Knowledge
In the previous introduction, we already know that Javascript does not have block-level scope, only function-level scope.
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
// 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.
// 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.
// 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.
// 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.
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.
// 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.
// 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.
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.
(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.
( // 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.
// 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

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

typedef struct is used in C language to create structure type aliases to simplify the use of structures. It aliases a new data type to an existing structure by specifying the structure alias. Benefits include enhanced readability, code reuse, and type checking. Note: The structure must be defined before using an alias. The alias must be unique in the program and only valid within the scope in which it is declared.

Variable expected value exceptions in Java can be solved by: initializing variables; using default values; using null values; using checks and assignments; and knowing the scope of local variables.

Advantages of JavaScript closures include maintaining variable scope, enabling modular code, deferred execution, and event handling; disadvantages include memory leaks, increased complexity, performance overhead, and scope chain effects.

The #include preprocessor directive in C++ inserts the contents of an external source file into the current source file, copying its contents to the corresponding location in the current source file. Mainly used to include header files that contain declarations needed in the code, such as #include <iostream> to include standard input/output functions.

Life cycle of C++ smart pointers: Creation: Smart pointers are created when memory is allocated. Ownership transfer: Transfer ownership through a move operation. Release: Memory is released when a smart pointer goes out of scope or is explicitly released. Object destruction: When the pointed object is destroyed, the smart pointer becomes an invalid pointer.

In JavaScript, the pointing types of this include: 1. Global object; 2. Function call; 3. Constructor call; 4. Event handler; 5. Arrow function (inheriting outer this). Additionally, you can explicitly set what this points to using the bind(), call(), and apply() methods.

Can. C++ allows nested function definitions and calls. External functions can define built-in functions, and internal functions can be called directly within the scope. Nested functions enhance encapsulation, reusability, and scope control. However, internal functions cannot directly access local variables of external functions, and the return value type must be consistent with the external function declaration. Internal functions cannot be self-recursive.

Closures in Java allow inner functions to access outer scope variables even if the outer function has exited. Implemented through anonymous inner classes, the inner class holds a reference to the outer class and keeps the outer variables active. Closures increase code flexibility, but you need to be aware of the risk of memory leaks because references to external variables by anonymous inner classes keep those variables alive.
