Detailed description of Javascript context and scope
This article attempts to explain the mechanism behind the context and scope in Javascript, mainly involving execution context), scope chain), closure ),this
.
Execution context
Execution context (context) determines the variables, functions, and data that can be obtained during Js execution. A program may be divided into many different contexts, each context is bound to a variable object (variable object), which is like a container used to store all the variables and functions that have been defined or can be obtained in the current context. The context at the top or outermost layer is called the global context. The global context depends on the execution environment, suchglobal
Andwindow
:
Note that the context and scope are different concepts. Js itself is a single process. Every time a function is executed, a new context is generated, which is pushed to the context stack of Js, the function is popped up after the execution is complete. Therefore, the Js interpreter is always executed in the context on the top of the stack. When a new context is generated, the variable object of the context is bound first, includingarguments
And the variables defined in the function. Then, the scope chain of the context will be created .)this
Assign the Object to which the function belongs. This process can be represented:
This
As mentioned abovethis
The Object to which the function belongs. Specifically, when a function is defined in a global pair,this
Point to global. When a function acts as the Object method,this
Point to this Object:
- var x = 1;
- var f = function(){
- console.log(this.x);
- }
- f(); // -> 1
-
- var ff = function(){
- this.x = 2;
- console.log(this.x);
- }
- ff(); // -> 2
- x // -> 2
-
- var o = {x: "o's x", f: f};
- o.f(); // "o's x"
As mentioned above, when a function is executed to generate a new context, the variable object of the current context is bound before the scope chain is created. We know that the function definition can be nested in the context created by other functions, or horizontally defined in the same context such as global ). In fact, the scope chain concatenates all variable objects bound to the context of the nested definition from the bottom up so that the nested function can "inherit" the variables of the upper context, the parallel functions do not interfere with each other:
- var x = 'global';
- function a(){
- var x = "a's x";
- function b(){
- var y = "b's y";
- console.log(x);
- };
- b();
- }
- function c(){
- var x = "c's x";
- function d(){
- console.log(y);
- };
- d();
- }
- a(); // -> "a's x"
- c(); // -> ReferenceError: y is not defined
- x // -> "global"
- y // -> ReferenceError: y is not defined
Closure
If you understand the context and scope chain mechanism mentioned above, you can see the concept of closure clearly. When a function is called, a new context and scope chain are created, and the scope chain is to concatenate the variable objects bound to the outer upper layer) context one by one, this allows the current function to obtain the variables and data of the outer context. If we define a new function in the function and return the inner function as the value, the scope chain contained in the inner function will be returned together, even if the inner function is executed in other contexts, the internal scope chain still maintains the original data, and the current context may not be able to obtain the data in the original outer function, so that the internal scope chain of the function is protected, to form a closure ". See the following example:
- var x = 100;
- var inc = function(){
- var x = 0;
- return function(){
- console.log(x++);
- };
- };
-
- var inc1 = inc();
- var inc2 = inc();
-
- inc1(); // -> 0
- inc1(); // -> 1
- inc2(); // -> 0
- inc1(); // -> 2
- inc2(); // -> 1
- x; // -> 100
Shows the execution process,inc
The scope chain generated when the anonymous function returned internally is created includesinc
Inx
, Even if it is assignedinc1
Andinc2
Thenglobal context
Their scope chain is still determined by the context in the definition.x
Yesfunction inc
Defined in, cannot be outerglobal context
Changes to achieve the closure effect:
This in closure
We have repeatedly mentioned that the execution context and scope are actually created and split through the function, whilethis
Unlike the scope chain, it is determined by the Object environment in which ** the function is executed **. This is also true.this
The most confusing and incorrect one. An example is as follows:
- var name = "global";
- var o = {
- name: "o",
- getName: function(){
- return this.name
- }
- };
- o.getName(); // -> "o"
Executiono.getName()
HourgetName
Boundthis
It is calledo
, So nowthis == o
; It is easier to confuse with closure:
- var name = "global";
- var oo = {
- name: "oo",
- getNameFunc: function(){
- return function(){
- return this.name;
- };
- }
- }
- oo.getNameFunc()(); // -> "global"
In this case, the closure function isreturn
The subsequent call is equivalent:
- getName = oo.getNameFunc();
- getName(); // -> "global"
For a more obvious example:
- Var ooo = {
- Name: "ooo ",
- GetName: oo. getNameFunc () // at this time, this of the closure function is bound to the new Object.
- };
- Ooo. getName (); //-> "ooo"
Of course, sometimes to avoidthis
When executed, it is replaced by the following method:
- var name = "global";
- var oooo = {
- name: "ox4",
- getNameFunc: function(){
- var self = this;
- return function(){
- return self.name;
- };
- }
- };
- oooo.getNameFunc()(); // -> "ox4"
Or forcibly define the executed Object during the call:
- var name = "global";
- var oo = {
- name: "oo",
- getNameFunc: function(){
- return function(){
- return this.name;
- };
- }
- }
- oo.getNameFunc()(); // -> "global"
- oo.getNameFunc().bind(oo)(); // -> "oo"
Summary
Javascript is a very interesting language. because many of its features are DOM operations in HTML, it seems random and slightly less rigorous, however, with the development of the front-end and the rise of Node, Js is no longer "toy language" or "CSS extension" in the jQuery era ", the concepts mentioned in this article are confusing or misunderstood for beginners and Js developers who have been overly involved in traditional Web development. I hope this article will be helpful.
The reason for writing this summary is that I shared the Learn javascript in one picture on Github. Some people initially questioned that this is only a syntax table syntax cheat sheet ), it does not involve more in-depth closures, scopes, and other content, but unexpectedly, this project has more than 3000 stars, so it cannot be used.