Write first: this is an article I wrote in the understanding JS series. The article is clear and easy to understand. It will be connected in series to form its own independent knowledge context. After reading the whole collection, I believe you will also gain something. Writing is not easy, I hope you can give me a thumbs-up!

To understand the JS series of topics

An overview of

  • Serving time: 10 minutes

  • Difficulty: simple, don’t run, watch and then walk

  • Edible value: Learn a few ways to change the direction of this.

  • Matting knowledge

    One article to understand JS series (10) thoroughly understand this direction, understand the original intention of this design and the basic rules of this direction.

    This article to understand the JS series (11) of this three special pointing, understanding this pointing in three special cases pointing problems.

    JS series (7) constructor, new, instance object, prototype, prototype chain, ES6 class, for the third kind, through new change this point has a great help.

Tips: Before reading this chapter, it is best to read the above two articles for the convenience of arrow functionsthisDirected understanding

Methods the directory

  • Use the arrow function of ES6
  • useapply,call,bind
  • newInstantiate an object
  • let vm = this;

Arrow function

Arrow functions are available as a feature in ES6.

In addition to reducing the amount of code, elegant writing and other features, it also changes the function of this pointing.

When this was designed, it was used to refer to the current runtime environment (execution context). The arrow function does not determine what this points to based on the call, but rather what this points to when the function is defined.

The main reason for this is that there is no this binding in the arrow function and its value must be determined by looking up the scope chain, so the arrow function refers to this in the outer scope.

If the arrow function is contained by a non-arrow function, then this is bound to this of the nearest non-arrow function; otherwise, this is undefined.

Because it does not have this, it cannot be used as a constructor

So, let’s use an example to understand the arrow function’s this point.

So let’s start with an example of a normal function,

Case 1:

var dog = {
  name: 'wangcai'.hello: function (){
    console.log(this.name)
  }
}
var name='windowName';
// Call the statement
dog.hello();   // wangcai
Copy the code

Because this always refers to the object that called it last, which was dog, the output value is wangcai.

So, next, let’s rewrite this example using the arrow function.

Example 2:

var dog = {
  name: 'wangcai'.// Declare a statement
  hello: () = >{
    console.log(this.name)
  }
}
var name='windowName';
dog.hello();     // windowName 
Copy the code

In this case, we can see that the output is windowName.

Why is the output value windowName instead of wangcai? First, the arrow function’s this points not to the calling statement, but to the declaration statement, which I understand, but dog.hello() I ignore.

The hello method is defined in the dog object, so don’t be fooled by its declared position.

Remember that the arrow function refers to this in the outer scope. Since it has no this binding, it must look up the scope chain to determine its value, so the arrow function refers to this in the outer scope.

But the object does not constitute a separate scope, so this here refers to the global object, i.e., window.

So, its output value is windowName.

Because the arrow function’s this points to a fixed point, it is convenient to encapsulate the callback function.

Also, arrow functions are not appropriate when defining object methods.

You can use the ES6 method shorthand instead:

var dog = {
  name: 'wangcai'.hello(){
      console.log(this.name); }}Copy the code

The above code is equivalent to:

var dog = {
  name: 'wangcai'.hello: function(){
      console.log(this.name); }}Copy the code

Apply, call, bind

The main reason for grouping these three methods together is that they can all change the this pointer, and they are all function methods.

The first thing to understand is that they are a method of a function.

Therefore, it should be written after the method. Its main function is to change the this direction of the current method.

To complete it is, in fact,

  • Function.prototype.apply()
  • Function.prototype.call()
  • Function.prototype.bind()

Of course, a watched pot never boils, so let’s uncover them all.

However, to facilitate your understanding, let’s take an example:

Example 3:

var dog = {
  name: 'wangcai'.hello(. rest){
    console.log(`The ${this.name}Like to eat${rest.join(', ')}`); }}var name='cooldream'
dog.hello('bone'.Article 'meat');    // Wangcai likes to eat bones and strips of meat
Copy the code

ES6 introduces the REST parameter (of the form… Variable name), used to get extra arguments to a function so you don’t need to use the arguments object. Rest is used to wrap up the remaining parameters and return them as an array.

Next, there are three ways to make Hello () point to the window by changing this.

apply

Function.apply(thisArg,[argsArray])

Apply () corresponds to the this reference to the given method, and executes it.

The first parameter is this, and the second parameter is the method call. The second parameter is in the format of an array.

So, we still use dog.hello(), but the difference is that we use apply() to change this to point to the window and print cooldream likes bullfrog pot, grilled chicken, and risotto

XDM, code:

var dog = {
  name: 'wangcai'.hello(. rest){
    console.log(`The ${this.name}Like to eat${rest.join(', ')}`); }}var name='cooldream'
dog.hello.apply(window['Bullfrog Pot'.'chicken'.'Rice Baked with cheese'])  // Cooldream likes to eat bullfrog pot, roast chicken, parfait rice
Copy the code

As you can see, we use apply(window) to refer this to the window with the first parameter thisArg.

call

Function.call(thisArg, arg1, arg2, ...)

The call() method and the apply method do the same thing, so I won’t go into details here.

If you forget, don’t go back to the top to continue reading, because I think you read this article, an hour will forget. (Just kidding, don’t ask why the bold, afraid you ran away), please consciously return to the upper view, review the old and learn new.

As you can see, the first parameter is exactly the same as apply, but the main difference is the second input parameter.

It’s a list of spliced lists.

Now, let’s rewrite this with call().

var dog = {
  name: 'wangcai'.hello(. rest){
    console.log(`The ${this.name}Like to eat${rest.join(', ')}`); }}var name='cooldream'
dog.hello.call(window.'Bullfrog Pot'.'chicken'.'Rice Baked with cheese')  // Cooldream likes to eat bullfrog pot, roast chicken, parfait rice
Copy the code

bind

Bind () essentially recreates a function that points to your first this entry, and it’s gone, okay? It doesn’t execute.

What else can you do? Just call it yourself.

Don’t write after, gee, my code doesn’t execute??

var dog = {
  name: 'wangcai'.hello(. rest){
    console.log(`The ${this.name}Like to eat${rest.join(', ')}`); }}var name='cooldream'
dog.hello.bind(window.'Bullfrog Pot'.'chicken'.'Rice Baked with cheese') ()// Cooldream likes to eat bullfrog pot, roast chicken, parfait rice
Copy the code
var dog = {
  name: 'wangcai'.hello(. rest){
    console.log(`The ${this.name}Like to eat${rest.join(', ')}`); }}var name='cooldream'
dog.hello.bind(window['Bullfrog Pot'.'chicken'.'Rice Baked with cheese') ()// Cooldream likes to eat bullfrog pot, roast chicken, parfait rice
Copy the code

It is not hard to see that it is acceptable for input arguments, lists, and arrays.

So, to sum up:

  • role

    Call Apply Bind can change the direction of this.

  • The ginseng

    Call and Apply have the same functions, but the way they enter parameters is different.

    Call accepts a concatenated list.

    Apply accepts arrays.

    Bind means either an array or a list.

  • Enforcement mechanism

    Call and Apply are performed immediately.

    Bind creates a new function, so it doesn’t execute itself and needs to be called.

new

The fact that a new in a constructor can change the direction of this depends on what the new does.

It’s not hard to understand how new is implemented.

This time to a bit of difficulty, their own implementation of new, promising, their own wheel.

So, let’s talk about what the new operator does

  1. Create a new object
  2. Empty the prototype address of the object_proto_A prototype object pointing to a constructor (the concepts of prototypes and prototype chains involved here are covered below)
  3. usingapplycallOr,bindThis points to obj from the binding object that used to point to window. (This way, when we pass an argument to a function, the object’s properties will be mounted to OBj.)
  4. Return this object

So, next we can implement a new method ourselves

// const xxx = _new(Person,'cooldream',24) ==> new Person('cooldream',24)
function _new(fn,... args){
    // Create a new object for the function variable object
    const newObj = {};
    // point the empty object's prototype address '_proto_' to the constructor's prototype object
    newObj.__proto__ = fn.prototype;
    // This points to a new object
    fn.apply(newObj, args);
    // Return this new object
    return newObj;
}
Copy the code

Actually, about implementing new on your own.

You can use apply, call or bind, depending on the mood. It feels good to be a pussy.

JS series (7) constructor, new, instance object, prototype, prototype chain, ES6 class, a complete understanding of the constructor, new, instance object, prototype, prototype chain, and ES6 class, these commonplace concepts between the relationship.

So, that’s why new can do the same thing.

let vm = this;

It’s a bit of a stretch to say that this changes the direction of this. But it’s also a way to do it.

In the outer layer of the function, we define a variable vm to hold this in the current environment.

Then, if the inner function wants to access the outermost this pointer, it simply needs to use the VM.

Functions can create separate scopes. Scopes, on the other hand, are outward accessible but not inward. That’s what we were talking about sticking your head out.

I don’t care what this refers to, I just know that VM must be the outermost this. No matter how deep a nested function accesses the VM, the VM is always the outermost this.

That’s all we have to say about this pointing.

Series directory

  • JS series (1) compilation principle, scope, scope chain, variable promotion, temporary dead zone

  • JS series (2) JS memory life cycle, stack memory and heap memory, deep and shallow copy

  • JS series (3) of garbage collection mechanism, memory leaks, closures

  • JS series (4) closure applications – Currization, partial functions

  • JS series (5) closure applications – anti – shake, throttling

  • To understand JS series (6) of micro task and macro task, Event Loop

  • JS series (7) constructor, new, instance object, prototype, prototype chain, ES6 class

  • JS series (8) easy to understand the Promise

  • Learn more elegant asynchronous solutions in JS Series 9

  • JS series (10) thoroughly understand this point

  • Three special directions of this in JS series (11)