Javascript from scope chain to closure _ javascript skills

Source: Internet
Author: User
Tags define local
This article mainly talks about closures from the scope chain. Closures (closure) are a difficult and characteristic of Javascript language. Many advanced applications rely on closures for implementation. This article describes how to learn closures, for more information, see Shenma is a closure
The concept of closure is justified.

A closure is a function that has the right to access variables in another function scope.
This concept is a bit difficult. Split it. In terms of concept, closures have two features:

  • 1. Functions
  • 2. Access variables in another function Scope

Before elasticsearch 6, Javascript only has the function scope concept, and does not have the block-level scope (but catch caught exceptions can only be accessed in the catch Block) concept (IIFE can create a local scope ). Each function scope is closed, that is, variables in the function scope cannot be accessed externally.

Function getName () {var name = "Beauty name"; console. log (name); // "Beauty name"} function displayName () {console. log (name); // error}

But in order to get the name of a beautiful girl, the Code was changed to this:

Function getName () {var name = "Beauty name"; function displayName () {console. log (name) ;}return displayName;} var beauty = getName (); beauty () // "Beauty name"

Now, the beauty is a closure, and the single Wang wants to play. (However, we do not recommend that you write variable names in Chinese ).

There are three more things about closures:
1. Closures can access variables other than the current function.

Function getOuter () {var date = '000000'; function getDate (str) {console. log (str + date); // access the external date} return getDate ('Today is: '); // "today is: 815"} getOuter ();

GetDate is A closure. When the function is executed, it will form A scope A. A does not define the variable date, but it can find the definition of the variable in the parent-level scope.

2. Even if the external function has returned, the closure can still access the variables defined by the external function.

Function getOuter () {var date = '000000'; function getDate (str) {console. log (str + date); // access the external date} return getDate; // external function return} var today = getOuter (); today ('Today is :'); // "today is: 815" today ('Tomorrow is not: '); // "tomorrow is not: 815"

3. The closure can update the value of an external variable.

Function updateCount () {var count = 0; function getCount (val) {count = val; console. log (count) ;}return getCount; // external function returns} var count = updateCount (); count (815); // 815 count (816); // 816

Scope chain
Is it possible to access the variables of external functions by using the Mao closure? So let's talk about the scope chain in Javascript.
Javascript has the execution context concept, which defines other data that variables or functions have the right to access and determines their respective behaviors. Each execution environment has a variable object associated with it. All variables and functions defined in the environment are stored in this object. You can use it as a common Javascript Object, but you can only modify its attributes, but cannot reference it.

Variable objects also have parent scopes. When you access a variable, the interpreter first searches for the identifier in the current scope. If no identifier is found, the interpreter searches for the parent scope, until the identifier of the variable is found or the parent scope no longer exists, this is the scope chain.

The range chain and prototype inheritance are a little similar, but there is a little difference: If the attributes of a common object cannot be found in the current object and its prototype, undefined is returned; however, if the queried attribute does not exist in the scope chain, a ReferenceError will be thrown.

At the top of the scope chain is a global object. For code in the global environment, the scope chain contains only one element: a global object. Therefore, when variables are defined in the global environment, they are defined in the Global object. When a function is called, The scope chain contains multiple scope objects.

  • Global Environment

A little more about the scope chain (the Redbook provides a detailed explanation of the scope and execution environment). Let's look at a simple example:

// my_script.js"use strict";var foo = 1;var bar = 2;

Two simple variables are created in the global environment. As mentioned above, the variable object is a global object.

  • Non-nested functions

Modify the code to create a function without function nesting:

"use strict";var foo = 1;var bar = 2;function myFunc() { //-- define local-to-function variables var a = 1; var b = 2; var foo = 3; console.log("inside myFunc");}console.log("outside");//-- and then, call it:myFunc();

When myFunc is defined, the identifier of myFunc is added to the current scope object (here it is a global object ), the identifier references a function object ). The function object contains the function source code and other attributes. One of the attributes we care about is the internal attribute [[scope]. [[Scope] refers to the current scope object. That is, the scope object that we can directly access when the function identifier is created (here it is a global object ).

It is important that the function object referenced by myFunc not only contains the code of the function, but also contains the scope object pointing to it when it is created.

When the myFunc function is called, a new scope object is created. The new scope object contains the local variables defined by the myFunc function and its parameters (arguments ). The parent scope object of this new scope object is the scope object that we can directly access when running myFunc.

  • Nested functions

As mentioned above, when the function return is not referenced, it will be recycled by the garbage collector. But for a closure (function Nesting is a simple way to form a closure), even if an external function returns, the function object will still reference the scope object when it is created.

"Use strict"; function createCounter (initial) {var counter = initial; function increment (value) {counter + = value;} function get () {return counter ;} return {increment: increment, get: get};} var myCounter = createCounter (100); console. log (myCounter. get (); // returns 100myCounter. increment (5); console. log (myCounter. get (); // returns 105

When createCounter (100) is called, both increment and get built-in functions have references pointing to createCounter (100) scope. If createCounter (100) does not return any value, then the createCounter (100) scope is no longer referenced, so it can be recycled. However, because createCounter (100) actually has a returned value and the returned value is stored in myCounter, the reference relationship between objects changes.

It takes some time to think about it: Even if createCounter (100) has returned, it still has a scope and can only be accessed by inline functions. You can directly access the scope of createCounter (100) by calling myCounter. increment () or myCounter. get.

When myCounter. increment () or myCounter. when get () is called, a new scope object will be created, and the parent scope object of this scope object will be the currently accessible scope object.

When return counter; is executed, the corresponding identifier is not found in the scope of get (), and it will be searched up along the scope chain until the counter variable is found, then return the variable. Calling increment (5) is more interesting. When increment (5) is called separately, the parameter value is stored in the current scope object. To access the value, the function can immediately find the variable in the current scope. But when the function is to access counter, it is not found, so it searches up along the scope chain and finds the corresponding identifier in the scope of createCounter (100), increment () the counter value is modified. There is no other way to modify this variable. The powerful closure is that it can store private data.

Similar function objects, different scope objects
For the counter example above, let's talk about expansion. Check the Code:

//myScript.js"use strict";function createCounter(initial) { /* ... see the code from previous example ... */}//-- create counter objectsvar myCounter1 = createCounter(100);var myCounter2 = createCounter(200);

After myCounter1 and myCounter2 are created, the relationship graph is in soy sauce:

In the preceding example, the function objects of myCounter1.increment and myCounter2.increment have the same code and attributes (name, length, and so on ), however, their [[scope] points to different scope objects.

The following result is returned:

Var a, B; a = myCounter1.get (); // a equals 100b = myCounter2.get (); // B equals 200myCounter1. increment (1); myCounter1.increment (2); myCounter2.increment (5); a = myCounter1.get (); // a equals 103b = myCounter2.get (); // B equals 205

Scope and this
The scope stores variables, but this is not part of the scope. It depends on how the function is called. For a summary of this point, you can refer to this article: JavaScript interview questions: event Delegate and this

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.