Deep understanding ofJavaScript
thethis
Pointer 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.this
What 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.this
The 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,this
The 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 separate
this
- Can’t pass
Call, apply, bind
Methods to changethis
Point to (because there is no 😂) - Is not binding
arguments
- You can’t use
new
Operator (because there is nonethis
😂) - There is no
prototype
(See my last article for details.) - Cannot be used as a function generator and cannot be used in arrow functions
yield
- Unless the arrow function has a normal function nested within it, will
yield
It’s used in ordinary functions
- Unless the arrow function has a normal function nested within it, will
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
- will
this
Bind 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, pass
bind
The bindingthis
After, you need to execute the function manually. Such asgetName.bind(obj, '111')()
- The parameter transmission mode and
call
The 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:
- bar
- bar
- fooBar
- 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.