About variable scope understanding in JavaScript

Source: Internet
Author: User
Tags closure variable scope

Now in conjunction with an article on the Web, review the scope of this thing. Scopes and contexts are not the same thing, and many people may confuse it. Each function call is associated with a scope and a context. Fundamentally, scopes are based on functions and contexts are object-based. In other words, the scope is associated with the variable that the function call is capable of acquiring, and it is unique to each invocation. The context often represents the value of this variable, which points to the object that owns the code currently executing.

Variable scope

The scope of a variable is the region in the program source code that defines the variable. Global variables have global scope, and are defined anywhere in the JS code. However, the variables declared within the function are defined only within the function body, they are local variables, the scope is local, and function parameters are local variables, and they are defined only in the function body. Local variables in the function body have precedence over global variables of the same name, and global variables are obscured by local variables if a local variable declared in the function body or with the same variable as the one in the function argument and the same as the global variable.

JavaScript does not currently support block scopes, where you can define a variable scope in an if declaration, a switch declaration, a for loop, or a while loop. This means that the variable cannot be fetched outside the opening and closing curly braces. At present, any variable defined within a block can be acquired outside the block. However, this situation is about to change, in order to support the definition of block scope variables, the Let keyword has been increased by the official to the ES6 standard.

The "This" context

The context often determines how a function is invoked. When a function is called as a method of an object, this points to the object that called the method:

The code is as follows Copy Code

var object = {foo:function () {alert (this = = object);}};

Object.foo (); True '

The same principle applies when you define an object instance using the new operator. In this case, this point within the scope of the function points to the newly created instance:

The code is as follows Copy Code

function foo () {alert (this);}

Foo ()//Window new Foo ()//foo '

When called as an unbound object, this defaults to the global context or the Window object in the browser. However, if the function is executed in strict mode, the context will be default to undefined

Execution context and scope chain

JavaScript is a single-threaded language, which means you can only do one thing at a time in the browser environment. When the JavaScript interpreter initializes the execution code, it first enters a global execution context by default. On this basis, each call to the function creates a new execution context.

This is usually where the confusion arises, where the "execution context" actually corresponds to all intents and purposes that point to the scope, which is different from the context discussed earlier. This is a bad name management, but unfortunately it has been defined in the ECMAScript standard, which is a bit unacceptable.

Each time a new execution context is created, it is added to the top of the scope chain (sometimes called the execution stack or call stack). The browser always executes the execution context currently at the top of the scope chain. Once executed, it is removed from the top of the stack and returned control to the execution context below it. For example:

function A () {second (); function second () {third (); function third () {fourth (); function fourth () {//Do something}} }
} a (); Running the top code causes nested functions to execute all the way up to the fourth function. The role at this point in the order of Julien from top to bottom is: fourth,third,second,first,global. The fourth function can get to global variables and any variables defined in First,second,third and functions. Once the fourth function completes, it will be removed from the scope and execution will be returned to the third function. This process continues until all code is executed.

Naming conflicts in different execution contexts are resolved by the ascent of the scope chain (climbing up the scope chain), which is moved from local to global. This means that local variables that have the same name and are above the scope chain are given priority.

An execution context is divided into two phases: creation and execution. During the creation phase, the interpreter first creates a variable object (also become an active object), which consists of all the variables defined in the execution context, function declarations, and parameters. Start here. The scope connection is initialized, and the value of this is subsequently determined. Then in the execution phase, the code is interpreted and executed.

In short, every time you try to get a value in the execution context of a function, the query process will always start with its own variable object. If the variable is not found in the variable object, the search will move to the scope chain. It will climb the scope chain to check each execution context to see if a variable with a name match is found.

Closed Bag

When a nested function attempts to get a value outside of an external function, the closure is generated, and it is executed after the external function returns. It will retain the ability to obtain local variables for external functions, as well as functions that are defined internally. Encapsulation allows us to hide and hold the execution context from an external scope and use it for future manipulation, while exposing a common interface. The following is a simple example:

The code is as follows Copy Code

function foo () {var local = ' private variable '; return function bar () {return local;}}

var getlocalvariable = foo (); GetLocalVariable ()//private variable one of the most popular closures types is the widely circulated modular model. It allows you to simulate public, private, and privileged members:

  code is as follows copy code

var Module = (function () {var privateproperty = ' foo ';

Function Privatemethod (args) {
   //do something
}
return {
    Publicproperty: "",
    publicmethod:function (args) {
        //do something
   },
    privilegedmethod:function (args) {
         Privatemethod (args);
   }
}
}) ();

The process of executing this module seems to be performed after the compiler interprets it as a monomer. The only members that can be obtained outside the execution context of this closure are the properties and methods (such as Module.publicmethod) in which you return the object. However, because the execution context is protected, all private properties and methods remain active throughout the lifetime of the application, which means that all variables will be available in the future through a common method.

Another type of closure is called an immediate execution function expression (iife), which is simply an anonymous function that is invoked in the context of the window:

The code is as follows Copy Code

function (window) {

var a = ' Foo ', B = ' bar ';
function Private () {
Do something
}
Window. Module = {
Public:function () {
Do something
}
};
}) (this);

This expression is useful when trying to maintain the global namespace, and any variable that lives within the function is a local variable for the closure, but they will always remain active during the run. This is a good way to encapsulate the source code for applications and frameworks, especially when exposing a global interface for interaction.

Call and apply

Here are two simple methods within all functions that allow you to perform any function in any desired context. The call function requires an explicit list of parameters, and apply requires that you provide parameters in the form of an array:

The code is as follows Copy Code
function User (I, last, age) {
Do something
}
User.call (window, ' John ', ' Doe ', 30);
user.apply (window, [' John ', ' Doe ', 30]);

The results of the above two function calls are the same, and the user function is invoked in the window context and is given three parameters.

ECMAScript 5 Introduces the Function.prototype.bind method to manipulate the context. It returns a function that is permanently bound in the context of the first parameter of the BIND function, regardless of how the function is used. It is implemented by using a closed package that redirects calls in the appropriate context. Here's how to implement this in browsers that do not support bind:

The code is as follows Copy Code
if (! (' Bind ' in Function.prototype)} {Function.prototype.bind = Function () {var fn = this, context = arguments[0], args = ARRAY.P Rototype.slice.call (arguments, 1); return function () {return fn.apply (context, args);}} }`

This is common in situations where context is frequently lost: object-oriented and event handling. This is necessary because the AddEventListener method of a node always executes the callback function in the context in which the node event handler is bound, and it should do the same. However, if you want to use a more advanced object-oriented technique that does not require an object's method as a callback function, you need to manually adjust the context. The following is an example of the use of the BIND function:

The code is as follows Copy Code

function MyClass () {this.element = document.createelement (' div '); This.element.addEventListener (' Click ', This.onClick.bind (this), false); }

MyClass.prototype.onClick = function (e) {//Do something};

When you look back at the code for the BIND function, you may notice that one line of code involves a method of the array object:

' Array.prototype.slice.call (arguments, 1); The interesting point is that the arguments object here is not really an array, but it is often described as an object of a class array, and the Bigu period is more like a list of nodes (something returned by Document.getelemntsbytagname). They contain a length property and index values but they are still not arrays and therefore do not support the native methods of any array such as slice and push. However, because they are too similar, the array method can be used or hijacked. In the above example, the method of an array object is executed in the context of a class array object.

This technique of using another object method is also applied to object-oriented programming in JavaScript, which simulates traditional inheritance methods:

The code is as follows Copy Code
MyClass.prototype.init = function () {//In the context of the "MyClass" instance, the Init method MySuperClass.prototype.init.apply for the superclass is invoked (this, arguments); }

By invoking the superclass (Mysuperclass) method in the context of a subclass (MyClass) instance, we can emulate this powerful design pattern.

Conclusion

Before you begin to learn more advanced design patterns, it is important to understand these concepts because scopes and contexts have an important and fundamental role in the edge of modern JavaScript. Whether we talk about closures, object-oriented or inherited, or the implementation of multiple events, context and scope chains play a very important role. If your goal is to master the JavaScript language and understand it better, then the scope chain and closures should be the starting point for your learning.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.