Deep understanding ofJavaScriptthethisPointer to the

Hello everybody, here I go again. In the last article, we looked at JavaScript prototypes that interested students can access through a portal. Today we’ll talk about JavaScript’s this. Let’s explore this tricky question. Without further ado, let’s get down to business 👇👇👇

1.thisWhat exactly is the pointer

Let’s start with the first question. If you want to understand this, you have to know what it is. Let’s start with an example.

This is a little dog. --> This is a little dogCopy the code

This is a dog.

A flash of inspiration, gee, seems to understand something.

No hurry, let’s move on,

this.name = "Two Dogs"
Copy the code

From this sentence, we can quickly know that the name of the dog is two dogs. Now imagine pointing your finger at other dogs, kittens…

this is a cat.
this.name = "The ball ball" // This is a cat, its name is Ball ball

this is a other little dog. 
this.name = "The dog left the son." // This is another puppy, his name is Dog Shengzi

// As an English dud, the author's heart is broken.
Copy the code

When you look at this, it suddenly becomes clear to you that “this” is who we point to.

Wow, it feels like opening the door to a new world, this is so easy.

Here we go!!

What is this?

It’s a generation, and we often say that in JavaScript everything is an object, so this is a generation of objects, and it depends on who your finger is pointing at.

Do you need to consolidate?

This is me. This is my brother. This is a people. …………………………Copy the code

Forget the annoying English, code is what I’m after…

2.thisThe exact point of a pointer

To figure out what object this refers to, the key is to figure out what it refers to.

2.1 Functions without closures

Closures will be covered in a later chapter, so stay tuned.

1.

In general,thisThe generation refers to the object from which it is called (except for closure and arrow functions, explained later).

How to understand this sentence? Chestnut comes on


      
<html lang="en"><head><meta charset="UTF-8"></head><body></body></html>
<script>
  function getName () {
    console.log(this= = =window) // true
  }

	/ / call
  getName()
</script>
Copy the code

Here we define a getName function. It doesn’t specify who called it, so where does this point to?

2.

The global methods and properties are the methods and properties of the Window object, that is, the call is window.getName(), which is called by the window, meaning its this refers to the window

Don’t understand? All right, one more chestnut


      
<html lang="en"><head><meta charset="UTF-8"></head><body></body></html>
<script>
  let obj = {
    getName: getName
  }
  function getName () {
    console.log(this= = =window) // false
    console.log(this === obj) // true
  }
  obj.getName()
</script>
Copy the code

Define an object, use getName as the object’s method, and then execute it through obj.getName(). You’ll be surprised to find that this already refers to obj. The reason: the object calling the function is obj

2.2 Functions with closures

As we all know, timers are also a type of closure, so in case you get confused about the code, we’ll use timers to implement closures.

It’s the same recipe, the same flavor, the same chestnuts.


      
<html lang="en"><head><meta charset="UTF-8"></head><body></body></html>
<script>
  let obj = {
    getName: getName
  }
  function getName () {
    setTimeout(function xiaosan() {
      console.log(this === obj) // false
    }, 0)
  }
  obj.getName()
</script>
Copy the code

What!!!!! Isn’t it called by OBj? Student: Would this point to obj instead? Is who after all, is who let originally faithful love appeared crack?

Hold on, hold on, let’s see. Obj invoked getName. But xiaosan in the timer is not called by obj, so this definitely doesn’t point to OBj. So who does Xiaosan’s this point to? Let’s rewrite setTimeout as the following

setTimeout(function xiaosan() {
  console.log(this) // window
}, 0)
Copy the code

Oh, so Window is the other woman. Finally got you.

Witness the miracle of the moment, let us for the dislocation of love reset it!


      
<html lang="en"><head><meta charset="UTF-8"></head><body></body></html>
<script>
  let obj = {
    getName: getName
  }
  function getName () {
    setTimeout(function xiaosan() {
      console.log(this === obj) // true
    }.bind(this), 0)
  }
  obj.getName()
</script>
Copy the code

It was a big sigh of relief.

3.

The this in the closure points to window. You can change this by using arrow functions, call, apply, bind, etc.

2.3 Arrow Function

First, the down-arrow function. The official documentation states that the arrow function has the following features:

  • There are no separatethis
  • Can’t passCall, apply, bindMethods to changethisPoint to (because there is no 😂)
  • Is not bindingarguments
  • You can’t usenewOperator (because there is nonethis😂)
  • There is noprototype(See my last article for details.)
  • Cannot be used as a function generator and cannot be used in arrow functionsyield
    • Unless the arrow function has a normal function nested within it, willyieldIt’s used in ordinary functions

I look at this and I suddenly realize that the arrow function is too bad that so many things can’t be done. With all these restrictions, why use arrow functions?

There are a lot of advantages, but here we’ll only cover the arrow functions that are relevant to this lesson, which can “automatically bind” this

Here’s an example:


      
<html lang="en"><head><meta charset="UTF-8"></head><body></body></html>
<script>
  let obj = {
    getName: (a)= > {
      console.log(this === obj) // false
    },
    getAge: function () {
      console.log(this === obj) // true
    }
  }

  obj.getName()
  obj.getAge()
</script>
Copy the code

The first of the same two method calls returns false. Why is that? I’m calling it using obj. Hold on, let’s print this, see where it points to.

getName: (a)= > {
  console.log(this) // window
},
Copy the code

4.

Arrow functions do not create their own this, but only inherit this from the upper level of the scope chain

The upper layer of scope here is the Window object, so this refers to the window.

Let’s look again at the arrow function in the closure


      
<html lang="en"><head><meta charset="UTF-8"></head><body></body></html>
<script>
  let obj = {
    getName: getName
  }
  function getName () {
    setTimeout((a)= > {
      console.log(this === obj) // true
    }, 0)
  }
  obj.getName()
</script>
Copy the code

Now we have changed xiaosan to an arrow function, and we are surprised to find that this points to obj. This is obj, inherited from getName.

3. Modify the pointer to this

Manually changing the this pointer will help us know exactly what method we want to execute. There are three ways to change a pointer.

  • call
  • apply
  • bind

3.1 the call and apply

The two brothers are similar in character, so let’s introduce them together.

The biggest benefit of using call() or apply() to extend the scope is that the object does not need to have any coupling with the method,

What they do is set the value of this inside the function. That’s what we’re saying about changing the direction of this. How did that change?

😏 Little chestnut will appear again.

Call’s little chestnut

      
<html lang="en"><head><meta charset="UTF-8"></head><body></body></html>
<script>
  let obj = {
    name: 'An object'.getName: function (a,b,c) {
      globalGetName.call(this,a,b,c)
    }
  }
  function globalGetName (a,b,c) {
    console.log(this.name,a,b,c) // An object is xiaosan xiaosi xiaowu
  }
  obj.getName("xiaosan"."xiaosi"."xiaowu")
</script>
Copy the code

5.

The characteristics of the call

  • Bind this to the current environment,

  • Parameters are passed in one by one.

Apply’s chestnut

      
<html lang="en"><head><meta charset="UTF-8"></head><body></body></html>
<script>
  let obj = {
    name: 'An object'.getName: function (a,b,c) {
      globalGetName.apply(this,[a,b,c])
    }
  }
  function globalGetName (a,b,c) {
    console.log(this.name,a,b,c) // An object is xiaosan xiaosi xiaowu
  }
  obj.getName("xiaosan"."xiaosi"."xiaowu")
</script>
Copy the code

6.

The characteristics of the apply

  • willthisBind to the current environment,
  • Pass in a list of arguments, such as[a,b,c].

3.2 the bind

After calling the bind method, the first argument passed in bind is bound to the current function as this. Subsequent arguments are passed into the function one by one.


      
<html lang="en"><head><meta charset="UTF-8"></head><body></body></html>
<script>
  let obj = {
    name: 'An object'
  }
  function getName (a) {
    console.log(this.name, a)
  }
  getName.bind(obj, '111') ()// an object 111
</script>
Copy the code

As you can see, we pass in obj via getName.bind as this for getName. So when we execute getName, the this generation refers to the obj object. So this.name === obj.name. The second parameter is passed to getName as an input.

7.

The characteristics of the bind

  • Does not automatically execute, passbindThe bindingthisAfter, you need to execute the function manually. Such asgetName.bind(obj, '111')()
  • The parameter transmission mode andcallThe same

First of all, congratulations on seeing you here, which means my article isn’t so boring after all. Next, I will explain the conversion of this pointer in detail through an interview question. Are you ready? Let’s go…

4. Instructions for interview questions

var foo = 'fooBar'
var obj = {
  foo: "bar".func: function () {
    var self = this;
    console.log(this.foo); / / 1
    console.log(self.foo); / / 2
    (function () {
      console.log(this.foo); / / 3
      console.log(self.foo); / / 4
    }());
  }
};
obj.func();
Copy the code

Output:

  1. bar
  2. bar
  3. fooBar
  4. Bar
Resolution:
  • When obj.func is executed, this refers to obj. Both 1 and 2 now have the normal orientation obj.foo

  • 3 Because in a closure this refers to a window, we will find the global foo = ‘fooBar’

  • 4 Since this is cached, self refers to obj again, self.foo === obj.foo.