A text to clarify the context in JavaScript

Time:2020-9-23

A text to clarify the context in JavaScript

background

This article is part of “in 2019, after reading this one, I will no longer be afraid of the front-end interview”

A text to clarify the context in JavaScript

Refer to what I wrote beforeBlogAnd extradata, share it to you, hope to bring some to youInspiration and help

For reprint, please contact the author for permission.

text

contextIt is an important concept in JavaScript. Maybe many friends are not very familiar with this concept, so change it toScope“And”closure“What about it? It’s just kind of nice.

Scopeand"Shut up"It’s all about andExecution contextTwo closely related concepts.

Before explaining what an execution context is, let’s review scope and closure.

Scope

First of all, what is scope?

Domain, that isRange

Scope, in fact, is a variable or functionAccessible range

It controls variables and functionsvisibility andlife cycle

The scope is also divided into:global scope“And”Local scope」。

Global scope:

If an object can be accessed anywhere, the object is a global object with a global scope.

Objects with global scope can be divided into the following situations:

  • Variables defined on the outermost layer
  • Properties of global objects
  • Variables that are implicitly defined anywhere (i.e., variables that are assigned directly without definition). Implicitly defined variables are defined in the global scope.

Local scope:

The scope of JavaScript is throughfunctionTo define.

A variable defined in a function only for this functionVisible inside

Such scopes are called local scopes.

Another concept is closely related to scope, which isScope chain

Scope chain

The scope chain is aaggregateContains a series of objects that can be used toretrievalThe categories that appear in the contextidentifier (variables, parameters, function declarations, etc.).

When the function is defined, it will save the collection of the parent variable object AO / VO in the internal attribute[[scope]]In, the set is called a scope chain.

  • Ao: activation object
  • Vo: variable object variable object

JavaScript usesLexical scope(static scope), functions run when they aredefinitionInstead of being in the scope ofimplementScope of.

Take a simple example:

var a = 3;
​
function foo () {
  console.log(a)
}
​
function bar () {
  var a = 6
  foo()
}
​
bar()

If JS uses dynamic scope, it should print 6 instead of 3

This example shows that javasript isStatic scope

Pseudo code for the scope chain of this function:

function bar() {
    function foo() {
       // ...
    }
}
​
bar.[[scope]] = [
  globalContext.VO
];
​
foo.[[scope]] = [
    barContext.AO,
    globalContext.VO
];

When the function is running, it copies the [scope] attribute to create a scope chain, then creates the variable object VO, and then adds it to the scope chain.

executionContextObj: {
   VO: {},
   scopeChain: [VO, [[scope]]]
}

Generally speaking, VO has a much larger scope than Ao. VO is responsible for concatenating the functions called.
VO is external, and Ao is internal to the function itself.

The concepts closely related to AO and VO include go and EC
https://blog.nixiaolei.com/20…

Let’s talk about closures.

closure

Closure is also a frequently asked question in an interview. The form of investigation is also very flexible, such as:

  • Describe what closure is
  • Write a closure code
  • What’s the use of closures
  • Give you an example of closure, let you modify, or see the output

What is the closure?

To be honest, closure is actuallyfunction, one can accessFree variableFunction of.

Free variable: a variable that is not declared inside a function.

Many so-called code specifications say that not abusing closures can cause performance problems. I certainly don’t quite agree with this statement, but this is put forward for some reasons.

After all, free variables in closures dobindingOn a block of code, it still works without the context in which it was created, and the people who use it may not be aware of it.

There are many forms of free variables in closures. Let me give you a simple example.

function add(p1){
   return function(p2){
     return p1 + p2;
  }
}
​
var a = add(1);
var b = add(2);
​
a(1) //2
b(1) // 3

In the above example, the code blocks of a and B functions are the same, but the results of executing a (1) and B (1) are different, because the free variables bound by them are different. The free variable here is actually P1 in the function body.

The introduction of free variables, can play andOOPInsideencapsulationIn the same way, we can encapsulate some unknown free variables in a layer of functions to achieve the same effectModule encapsulationIt also takes advantage of this feature.

Then I’ll tell you about the real case I met. It was last year’s interviewTencent QQ musicA written test question of:

for (var i = 1; i <= 5; i++) {
  setTimeout(function timer() {
    console.log(i)
  }, i * 1000)
}

This code will output a bunch6Let you change it. Output1, 2, 3, 4, 5

There are still many solutions, just two common ones.

  1. Solve with closure
for (var i = 1; i <= 5; i++) {
  ;(function(j) {
    setTimeout(function timer() {
      console.log(j)
    }, j * 1000)
  })(i)
}

useExecute function nowPass I into the function.

At this time, the value is fixed on the parameter J and will not change. When the timer closure is executed next time, the variable J of the external function can be used to achieve the purpose.

  1. [recommended] uselet
for (let i = 1; i <= 5; i++) {
  setTimeout(function timer() {
     console.log(i)
  }, i * 1000)
}

For the principle and related details of const and let, please refer to my other article:

[issue 13] mastering the basis of front-end interview series I: ES6

After explaining these two concepts, we will return to our theme,context

Execution context

First, what is the execution context?

In short, the execution context is JavaScriptexecution environment

When JavaScript executes aimplementWhen you code, you willestablishCorrespondingExecution context

The composition is as follows:

executionContextObj = {
  this,
  VO,
  Scopechain: scope chain, related to closure
}

Because javavscript isSingle threadYou can only handle one thing at a time, and other tasks will be placed in the specified contextStackIn line.

When the JavaScript interpreter initializes the execution code, it creates a global execution context on the stack, and then creates and presses a new execution with each function callContext stack

After the function is executed, the execution context is popped up.

Perform the steps of context establishment:

  1. Creation phase
  2. Initialize scope chain
  3. Create variable object
  4. Create arguments
  5. Scan function declaration
  6. Variable scan declaration
  7. Ask this
  8. Execution phase
  9. Initializing references to variables and functions
  10. Execution code

this

This is an important concept in JavaScript, and it is also a concept that many primary developers can easily confuse.

Let’s talk about it today.

First of all, this isRuntimeCan be confirmed, notWhen definedConfirmed.

This always points toCall the functionObject of.

To judge the direction of this is actually to judge the function where this is locatedWho belongs to

The execution of this will have different directions, which can be roughly divided into:

  • Point to the calling object
  • Point to global object
  • The new construct points to a new object
  • Arrow / call / bind

Let’s look at them one by one.

1. Point to the calling object

function foo() {
  console.log( this.a );
}
​
var obj = {
  a: 2,
  foo: foo
};
​
obj.foo(); // 2

2. Point to global objects

This situation is the easiest to test and to confuse people.

Let’s start with a simple example:

var a = 2;
function foo() {
  console.log( this.a );
}
foo(); // 2

No doubt about it.

Look at a little bit more complicated:

function foo() {
    console.log( this.a );
}
​
function doFoo(fn) {
    this.a = 4
    fn();
}
​
var obj = {
    a: 2,
    foo: foo
};
​
var a = 3
doFoo( obj.foo ); // 4

contrast:

function foo() {
    this.a = 1
    console.log( this.a );
}
function doFoo(fn) {
    this.a = 4
    fn();
}
var obj = {
    a: 2,
    foo: foo
};
var a = 3
doFoo(obj.foo); // 1

Do you see the difference?

You may ask whyanodoFooOfaWhat about it?

Is it the A in foofirstDid you read it?

If you print this of Foo and dofoo, you can know that their this is pointing towindowYes.

Their operation will change the value of a in window.It's not a priorityRead a set in foo.

Here’s a simple verification:

function foo() {
  setTimeout(() => this.a = 1, 0)
  console.log( this.a );
}
​
function doFoo(fn) {
  this.a = 4
  fn();
}
​
var obj = {
  a: 2,
  foo: foo
};
​
var a = 3
doFoo(obj.foo); // 4
setTimeout(obj.foo, 0) // 1

The results confirm our above conclusion, and there is no priority.

3. point to new object by constructing new

var a = 4
function A() {
  this.a = 3
  this.callA = function() {
    console.log(this.a)
  }
}
A() // returns undefined. A (). Calla will report an error. Calla is saved in window
a = new A()
a. Call() // 3, Calla is in the object returned by new a

4. apply/call/bind

Everyone should be familiar with it.

Make this point to the first parameter passed, and if the first parameter is null, undefined or not, it points to the global variable.

var a = 3
function foo() {
  console.log( this.a );
}
var obj = {
  a: 2
};
foo.call(obj); // 2
foo.call(null); // 3
foo.call(undefined); // 3
foo.call(); // 3
​
var obj2 = {
  a: 5,
  foo
}
obj2. foo.call () // 3, not 5
​
//Bind returns a new function
function foo(something) {
  console.log(this.a, something);
  return this.a + something;
}
var obj =
  a: 2
};
​
var bar = foo.bind(obj);
var b = bar(3); // 2 3
console.log(b); // 5

5. arrow function

Arrow function is special, itThere is no one of my own。 It usesClose execution context(function or global) this value:

var x=11;
var obj={
 x:22,
 say: () => {
   console.log(this.x);
 }
}
​
obj.say(); // 11
obj.say.call({x:13}) // 11
​
x = 14
obj.say() // 14
​
//Compare it
var obj2={
 x:22,
 say() {
   console.log(this.x);
 }
}
obj2.say();// 22
obj2.say.call({x:13}) // 13

summary

Above we introduced the systemcontextAnd relatedScopeclosurethisAnd other related concepts.

This paper introduces their functions, usage scenarios, differences and connections.

Hope to be helpful to you. If there is any mistake in the article, please correct it. Thank you.

last

If you think the content is helpful, you can pay attention to my official account “front-end e advanced” to understand the latest developments.

Also can contact me to join wechat group, there are many big people sitting in town, can discuss technology together, fish together. Learn and grow together!

A text to clarify the context in JavaScript