Home Web Front-end JS Tutorial JavaScript Advanced Series—Scope and Namespace

JavaScript Advanced Series—Scope and Namespace

Feb 08, 2017 am 09:35 AM

  • Implicit global variables

  • Local variables

  • Variable declaration hoisting

  • Name resolution order

  • Namespace

  • Conclusion

Although JavaScript supports code snippets created by a pair of curly braces, it does not support block-level scope; only function scope is supported.

function test() { // 一个作用域
    for(var i = 0; i < 10; i++) { // 不是一个作用域
        // count
    }
    console.log(i); // 10
}
Copy after login

Translator's Note: If the left bracket of the return object and return are not on the same line, an error will occur.

(Note: If it is not in an assignment statement, but in a return expression or function parameter, {...} will be parsed as a code segment, not as the literal syntax of the object . If automatic semicolon insertion is taken into account, this may lead to some subtle errors)

// 译者注:下面输出 undefined
function add(a, b) {
    return 
        a + b;
}
console.log(add(1, 2));
Copy after login

There is no explicit namespace definition in JavaScript, which means that all objects are defined in a Under the globally shared namespace.

Every time a variable is referenced, JavaScript will traverse the entire scope upward until it finds the variable. If the global scope is reached but the variable is still not found, a ReferenceError exception is thrown.

Implicit global variables

// 脚本 A
foo = &#39;42&#39;;

// 脚本 B
var foo = &#39;42&#39;
Copy after login

The above two scripts have different effects. Script A defines variable foo in the global scope, while script B defines variable foo in the current scope.

Again, the above effect is completely different. Not using var to declare variables will result in the generation of implicit global variables.

// 全局作用域
var foo = 42;
function test() {
    // 局部作用域
    foo = 21;
}
test();
foo; // 21
Copy after login

Declaring the foo variable without using the var keyword in the function test will overwrite the external variable with the same name. This may not seem like a big problem at first, but when you have thousands of lines of code, declaring variables without using var can lead to bugs that are hard to track down.

// 全局作用域
var items = [/* 数组 */];
for(var i = 0; i < 10; i++) {
    subLoop();
}

function subLoop() {
    // subLoop 函数作用域
    for(i = 0; i < 10; i++) { // 没有使用 var 声明变量
        // 干活
    }
}
Copy after login

The outer loop will terminate after the first call to subLoop because subLoop overwrites the global variable i. This error can be avoided by declaring the variable using var in the second for loop. Never omit the var keyword when declaring a variable unless this is the desired behavior affecting the outer scope.

Local variables

Local variables in JavaScript can only be declared in two ways, one is as a function parameter, and the other is declared through the var keyword.

// 全局变量
var foo = 1;
var bar = 2;
var i = 2;

function test(i) {
    // 函数 test 内的局部作用域
    i = 5;

    var foo = 3;
    bar = 4;
}
test(10);
Copy after login

foo and i are local variables within the function test, and the assignment to bar will overwrite the variable with the same name in the global scope.

Variable declaration hoisting (Hoisting)

JavaScript will hoist variable declarations. This means that both var expressions and function declarations will be hoisted to the top of the current 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];
    }
}
Copy after login

The above code will be converted before running. JavaScript will hoist var expressions and function declarations to the top of the current scope.

// var 表达式被移动到这里
var bar, someValue; // 缺省值是 &#39;undefined&#39;

// 函数声明也会提升
function test(data) {
    var goo, i, e; // 没有块级作用域,这些变量被移动到函数顶部
    if (false) {
        goo = 1;

    } else {
        goo = 2;
    }
    for(i = 0; i < 100; i++) {
        e = data[i];
    }
}

bar(); // 出错:TypeError,因为 bar 依然是 &#39;undefined&#39;
someValue = 42; // 赋值语句不会被提升规则(hoisting)影响
bar = function() {};

test();
Copy after login

The lack of block-level scope not only causes var expressions to be moved from inside the loop to the outside, but also makes some if expressions harder to read.

In the original code, the if expression seems to modify the global variable goo, but in fact it modifies the local variable after the promotion rule is applied.

Without knowledge of hoisting, the following code appears to throw a ReferenceError exception.

// 检查 SomeImportantThing 是否已经被初始化
if (!SomeImportantThing) {
    var SomeImportantThing = {};
}
Copy after login

Actually, the above code works fine because the var expression is hoisted to the top of the global scope.

var SomeImportantThing;

// 其它一些代码,可能会初始化 SomeImportantThing,也可能不会

// 检查是否已经被初始化
if (!SomeImportantThing) {
    SomeImportantThing = {};
}
Copy after login

Translator's Note: There is an article introducing hoisting on the Nettuts+ website, and the code in it is very enlightening.

// 译者注:来自 Nettuts+ 的一段代码,生动的阐述了 JavaScript 中变量声明提升规则
var myvar = &#39;my value&#39;;  

(function() {  
    alert(myvar); // undefined  
    var myvar = &#39;local value&#39;;  
})();
Copy after login

Name resolution order


All scopes in JavaScript, including the global scope, have a special name this pointing to the current object . There is also a default variable arguments in the function scope, which contains the parameters passed to the function. For example, when accessing the foo variable within a function, JavaScript will search in the following order:

  1. Whether there is a definition of var foo in the current scope.

  2. Whether the function formal parameters use the foo name.

  3. Whether the function itself is called foo.

  4. Go back to the previous scope and start again from #1.

Namespace

A common mistake caused by having only one global scope is naming conflicts. In JavaScript, this can be easily solved with anonymous wrappers.

(Note: Custom arguments parameters will prevent the creation of native arguments objects.)

(function() {
    // 函数创建一个命名空间

    window.foo = function() {
        // 对外公开的函数,创建了闭包
    };

})(); // 立即执行此匿名函数
Copy after login

Anonymous functions are considered expressions; therefore for callability, they are executed first .

( // 小括号内的函数首先被执行
function() {}
) // 并且返回函数对象
() // 调用上面的执行结果,也就是函数对象
Copy after login

There are some other ways to call function expressions. For example, the following two methods have different syntax, but the effect is exactly the same.

// 另外两种方式
+function(){}();
(function(){}());
Copy after login

Conclusion


It is recommended to use an anonymous wrapper (Translator's Note: that is, a self-executing anonymous function) to create a namespace. This not only prevents naming conflicts, but also facilitates the modularization of the program.

Also, using global variables is considered a bad habit. Such code is error-prone and costly to maintain.

The above is the content of JavaScript advanced series - scope and namespace. For more related content, please pay attention to the PHP Chinese website (www.php.cn)!


Statement of this Website
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

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: How To Unlock Everything In MyRise
1 months ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Usage of typedef struct in c language Usage of typedef struct in c language May 09, 2024 am 10:15 AM

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.

How to solve variable expected in java How to solve variable expected in java May 07, 2024 am 02:48 AM

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 and disadvantages of closures in js Advantages and disadvantages of closures in js May 10, 2024 am 04:39 AM

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.

What does include mean in c++ What does include mean in c++ May 09, 2024 am 01:45 AM

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.

C++ smart pointers: a comprehensive analysis of their life cycle C++ smart pointers: a comprehensive analysis of their life cycle May 09, 2024 am 11:06 AM

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.

Can the definition and call of functions in C++ be nested? Can the definition and call of functions in C++ be nested? May 06, 2024 pm 06:36 PM

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.

There are several situations where this in js points to There are several situations where this in js points to May 06, 2024 pm 02:03 PM

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.

The difference between let and var in vue The difference between let and var in vue May 08, 2024 pm 04:21 PM

In Vue, there is a difference in scope when declaring variables between let and var: Scope: var has global scope and let has block-level scope. Block-level scope: var does not create a block-level scope, let creates a block-level scope. Redeclaration: var allows redeclaration of variables in the same scope, let does not.

See all articles