Brief introduction
JavaScript has a feature called scope. Although the concept of scopes is not easy to understand for many novice developers, I will try to explain them to you as much as possible from the simplest point of view. Understanding scopes allows you to write more elegant, less-error code and can help you implement powerful design patterns.
What is a scope?
Scopes are the accessibility of your code at run time, variables, functions, and objects. In other words, the scope determines the visibility of the variables and other resources in your code in each region .
Why do I need scopes? Minimum access principle
So, what are the benefits of restricting the visibility of variables and not allowing everything in your code to be available anywhere? One advantage is that scopes provide a level of security for your code. In computer security, there is a general principle: users can only access what they currently need.
Think about the computer administrator. They have a lot of control over the company's systems and seem to even give them full access to accounts. Suppose you have a company with three administrators who have full access to the system and everything works fine. But there was a sudden accident, and one of your systems was attacked by a malicious virus. Now you don't know who's got the problem, do you? You realize that you should only give them the account of the basic user and give them full access only when needed. This can help you track changes and record everyone's actions. This is called the minimum access principle. Does it look familiar? This principle is also used in programming language design, which is called scope in most programming languages, including JavaScript, and then we will learn it.
In your programming journey, you will realize that scopes can improve performance, track bugs, and reduce bugs in your code. Scopes also address the problem of naming variables of different scopes with the same name. Remember to not confuse scopes and contexts. They are different characteristics.
Scopes in JavaScript
There are two types of scopes in JavaScript
When a variable is defined in a function, the variable is in a local scope, and the variable defined outside the function is subordinate to the global scope. Each function creates a new scope when it is called.
Global scope
When you write JavaScript in the document, you are already in the global scope. There is only one global scope in the JavaScript document. Variables defined outside the function are saved in the global scope.
The scope is by default globalvar name = ' Hammad ';
Variables in the global scope can be accessed and modified in other scopes.
var name = ' Hammad '; Console.log (name); Logs ' Hammad ' function logName () { console.log (name);//' name ' is accessible here and everywhere else} logName (); Logs ' Hammad '
Local scope
The variables defined in the function are in the local scope. And the function has a different scope each time it is called. This means that variables of the same name can be used in different functions. Because these variables are bound in different functions and have different scopes, they cannot be accessed from one another.
Global scopefunction someFunction () { //local scope # #1 function someotherfunction () { //local Scope # #2 c3/>}}//Global scopefunction anotherfunction () { //Local scope # #3}//Global Scope
Block statements
Block-level declarations include if and switch, and for and while loops, unlike functions, which do not create new scopes. A variable defined in a block-level declaration belongs to the scope in which the block resides.
if (true) { //this ' if ' conditional block doesn ' t create a new scope var name = ' Hammad ';//name was still in the Global scope} console.log (name); Logs ' Hammad '
The Let and const keywords are introduced in ECMAScript 6. These keywords can replace Var.
var name = ' Hammad '; Let likes = ' Coding '; const skills = ' Javascript and PHP ';
Unlike the Var keyword, the Let and const keywords support creating using local scopes in block-level declarations.
if (true) { //this ' if ' conditional block doesn ' t create a scope //name are in the global scope because of the ' V AR ' keyword var name = ' Hammad '; Likes is in the local scope because of the "let" keyword let likes = ' Coding '; Skills is in the local scope because of the ' const ' keyword const skills = ' JavaScript and PHP ';} console.log (name) ; Logs ' Hammad ' Console.log (likes); Uncaught Referenceerror:likes is not definedconsole.log (skills); Uncaught Referenceerror:skills is not defined
The lifetime of a global scope in an app is the same as the application. A local scope exists only during the execution of the function call.
Context
Many developers often confuse scopes and contexts, as if they were a concept. But that's not true. Scopes are the ones we talked about above, and the context usually involves the this value in some special parts of your code. Scope refers to the visibility of a variable, and the context refers to the value of this in the same scope. We can of course use the function method to change the context, which we'll discuss later. In the global scope, the context is always the Window object.
Logs:window {speechsynthesis:speechsynthesis, Caches:cachestorage, Localstorage:storage ...} Console.log (this); function Logfunction () { console.log (this);} Logs:window {speechsynthesis:speechsynthesis, Caches:cachestorage, Localstorage:storage ...} Because Logfunction () is a property of a objectlogfunction ();
If the scope is defined in the method of an object, the context is the object in which the method resides.
Class User { logName () { console.log (this); }} (new User). LogName (); Logs User {}
(new User). LogName () is a convenient form of creating an object associated to a variable and calling the LogName method. In this way you do not need to create a new variable.
One thing you might notice is that if you use the New keyword to invoke a function, the value of the context will be different. The context is set to an instance of the called function. Consider the above example, a function called with the new keyword.
function Logfunction () { console.log (this);} new Logfunction ();//logs Logfunction {}
When a function is called in strict mode (strict modes), the context defaults to undefined.
Execution Environment
In order to solve all the confusion we have learned from the above, "Environment" in the word "execution environment" refers to the scope rather than the context. This is a weird naming convention, but because of the JavaScript documentation, we have to agree.
JavaScript is a single-threaded language, so it can only perform individual tasks at the same time. Other tasks are arranged in the execution environment. When the JavaScript parser starts executing your code, the Environment (scope) is set to global by default. The global environment is added to your execution environment, which is actually the first environment in the execution environment.
Each function call will then add its environment to the execution environment. It is the same procedure to call a function, either inside or elsewhere.
Each function will create its own execution environment.
When the browser finishes executing the code in the environment, the environment pops up from the execution environment, and the state of the current environment in the execution environment is transferred to the parent environment. The browser always executes the execution environment at the top of the execution stack (in fact the innermost scope of your code).
There can be only one global environment, and the function environment may have any number.
The execution environment has two phases: Create and execute.
Create phase
The first stage is the creation phase, when the function has just been called but the code is not executed. There are 3 main things that happen during the creation phase.
- Creating Variable Objects
- Creating a Scope chain
- Sets the value of the context (this)
Variable Object
The Variable object (Variable object), also known as the active object (Activation objects), contains all variables, functions, and other declarations defined in the execution environment. When a function is called, the parser scans all resources, including function parameters, variables, and other declarations. When everything is loaded into an object, the object is a variable object.
Variableobject ': { //contains function arguments, inner variable and function declarations}
Scope chain
During the execution environment creation phase, the scope chain is created after the variable object. The scope chain contains variable objects. Scope chains are used to parse variables. When parsing a variable, JavaScript begins to look for the desired variable or other resource from the inner layer along the parent. A scope chain contains its own execution environment and variable objects that are contained in all parent environments.
' Scopechain ': { //contains its own variable object and other variable objects of the parent execution contexts}
Execution Environment Object
The execution environment can be represented by the following abstract object:
Executioncontextobject = { ' Scopechain ': {},//contains its own variableobject and other variableobject of the parent Execution contexts ' Variableobject ': {},//contains function arguments, inner variable and function declarations
' this ': Valueofthis}
Code Execution phase
The second phase of the execution environment is the code execution phase, which performs additional assignment operations and the code is eventually executed.
Lexical scopes
Lexical scopes mean that within a function nesting, the inner function can access resources such as variables of the parent scope. This means that the lexical of the child function is bound to the parent execution environment. Lexical scopes are sometimes related to static scopes.
function grandfather () { var name = ' Hammad '; Likes is isn't accessible here function parent () { //name was accessible here //likes isn't accessible here function Child () { //innermost level of the scope chain //name was also accessible here var likes = ' Cod ing '; }} }
You may have noticed that the lexical scope is forward, meaning that the child execution environment can access name. But not by the parent backwards, meaning that the parent cannot access likes. This also tells us that variable precedence of the same name in different execution environments increases from top to bottom of the execution stack. One variable has the same name as another variable, and the inner function (the environment that performs the top of the stack) has a higher priority.
Closed Package
The concept of closures is closely related to the lexical scopes we have just learned. A closure is generated when an intrinsic function tries to access the scope chain of an external function (a variable outside the lexical scope). Closures include their own scope chains, parent scope chains, and global scopes.
Closures can access not only variables of external functions, but also parameters of external functions.
Even if the function has already been return, the closure can still access the variables of the external function. This means that the return function allows continuous access to all resources of the external function.
When your external function return an intrinsic function, the return function is not called when the external function is called. You must first save the call to the external function with a separate variable, and then call the variable as a function. Look at the following example:
function greet () { name = ' Hammad '; return function () { console.log (' Hi ' + name) ,}} greet ();//Nothing happens, no errors//the Returned function From greet () gets saved in Greetlettergreetletter = Greet (); Calling Greetletter calls the returned function from the greet () Functiongreetletter (); Logs ' Hi Hammad '
It is worth noting that even after the greet function return, the Greetletter function can still access the name variable of the greet function. If you do not use a variable assignment to call the function of the greet function return, one method is to use () two times () (), as follows:
function greet () { name = ' Hammad '; return function () { console.log (' Hi ' + name);} } greet () ();//Logs ' Hi Hammad '
Shared scopes and private scopes
In many other programming languages, you can set the visibility of variables and methods in a class through public, private, and protected scopes. Look at the following example of PHP
Public scopepublic $property;p ublic Function method () { //...}//Private sccpeprivate $property;p rivate function Method () { //...}//Protected scopeprotected $property;p rotected Function method () { //...}
Encapsulate functions from the public (global) scope so that they are protected from attack. In JavaScript, however, there are no shared scopes and private scopes. However, we can implement this feature with closures. In order for each function to be detached from the global, we will encapsulate them in the function shown below:
(function () { //private scope});
The parentheses at the end of the function tell the parser to execute this function immediately. We can add variables and functions to the external inaccessible. But if we want to access them externally, that is to say we want them to be part of the public and partly private. We can use a form of closures called module pattern, which allows us to partition functions with public scopes and private scopes in an object.
Module mode
The module mode is as follows:
var Module = (function () { function Privatemethod () { //do something } return { Publicmethod: function () { //Can call Privatemethod (); } };}) ();
The return statement of the Module contains our public functions. The private function has not been return. The function has not been return to ensure that they are inaccessible in the Module namespace. But our shared functions have access to our private functions, which make it easier for them to use useful functions, AJAX calls, or something else.
Module.publicmethod (); Worksmodule.privatemethod (); Uncaught Referenceerror:privatemethod is not defined
A habit is to use an underscore as a starting-name private function and return an anonymous object that contains a common function. This makes them easy to manage in very long objects. To the following:
var Module = (function () { function _privatemethod () { //do something } function Publicmethod () {
//do something } return { publicmethod:publicmethod, }}) ();
Execute function expression immediately (iife)
Another form of closure is the immediate execution of a function expression (immediately-invoked function Expression,iife). This is an anonymous function that is called from within the context of the window, which means that the value of this is window. It exposes a single global interface for interaction. As shown below:
(function (window) { //Do Anything}) (this);
Use. Call (),. Apply () and. bind () to change the context
Call and Apply functions to change the context of a function invocation. This gives you the magical ability to program (and ultimately the ability to rule the world). Instead of using parentheses to invoke a function, you only need to use the call and apply functions and pass the context as the first parameter. The function's own arguments can be passed in after the context.
function Hello () { //do something ...} hello ();//The usually call Ithello.call (context); s the context (value of this) as the first argumenthello.apply (context); Here's can pass the context (value of this) as the first argument
The difference between. Call () and. Apply () is that other parameters in call are separated by commas, and apply allows you to pass in an array of arguments.
function introduce (name, interest) { Console.log (' hi! I ' m ' + name + ' and I like ' + Interest + '. '); Console.log (' The value of this was ' + this + '. ')} Introduce (' Hammad ', ' Coding '); The usually call Itintroduce.call (Windows, ' Batman ', ' to save Gotham '); Pass the arguments one by one after the contexttintroduce.apply (' Hi ', [' Bruce Wayne ', ' businesses '); Pass the arguments in an array after the context//output://hi! I ' M Hammad and I like coding.//the value of this is [object window].//hi! I ' M Batman and I like to save gotham.//the value of that is [object window].//hi! I ' m Bruce Wayne and I like businesses.//the value of this is Hi.
Call is a little more efficient than Apply.
The following example lists all the items in the document and then prints them on the console in turn.
<! DOCTYPE html>The HTML document contains only one unordered list. JavaScript selects them from the DOM. The list item is recycled from beginning to end. In the loop, we output the contents of the list item to the console.
The output statement is contained in a function enclosed by parentheses and then called the call function. The corresponding list item is passed into the call function to ensure that the console outputs the correct object's InnerHTML.
Objects can have methods, and the same function objects can have methods. In fact, the JavaScript function has 4 built-in methods:
Function.prototype.apply () Function.prototype.bind () (introduced in ECMAScript 5 (ES5)) Function.prototype.call () Function.prototype.toString ()
Function.prototype.toString () returns a string representation of the function code.
So far, we have discussed. Call (),. Apply (), and ToString (). Unlike call and Apply, bind does not invoke the function itself, it simply binds the context and other parameters before the function call. Use Bind in the example mentioned above:
(function introduce (name, interest) { Console.log (' hi! I ' m ' + name + ' and I like ' + Interest + '. '); Console.log (' The value of this was ' + this + '. ')}). Bind (window, ' Hammad ', ' cosmology ') (); logs://hi! I ' M Hammad and I like cosmology.//the value of that is [object Window].
Bind, like the call function, separates other incoming parameters with commas, and does not pass in an array of arguments as apply.
ConclusionThese concepts are the basis of JavaScript and it is important to understand them if you want to delve deeper. I hope you have a better understanding of JavaScript scopes and related concepts. If there is something unclear, you can ask a question in the comment area.
Scope often accompanies your code around, enjoy coding!
Front-End Technology Bookcase list: Https://github.com/jobbole/awesome-web-dev-books
Original address: http://web.jobbole.com/91134/
Understanding JavaScript Scopes (GO)