1. What is this
In JS, there is an amazing this mechanism
Let’s start with an example:
var person = {
namer: 'Joe'.sayNmae: function() {
console.log(namer); }}var namer = 'bill'
person.sayNmae(); / / li si
Copy the code
Oh, my God. What’s wrong with what we thought?
This is because the variables in the sayNmae method are under the global scope, but we want to access the variables in the object
Using this allows us to access variables inside the object
var person = {
namer: 'Joe'.sayNmae: function() {
console.log(this.namer); }}var namer = 'bill'
person.sayNmae(); / / zhang SAN
Copy the code
This is because the this in the method refers to the object of the method
this
It’s an object
classification
This is divided into this in the global scope and this in the function
This in the global scope refers to a Windows object
The reference to this in a function is a little bit more complicated, so we’re going to look at the reference to this in a little bit more detail
2. In the functionthis
The point to
The reference to this is determined when we call the function. Different methods called result in different references to this
Call way | This points to the |
---|---|
Ordinary function calls | window |
Constructor call | Instance objectsMethods inside the prototype object also point to the instance object |
Object call method | The object to which the method belongs |
Event binding function | Bind event object |
Timer function | window |
Execute function immediately | window |
Arrow function | Arrow functionthis That’s the outer functionthis |
1. Ordinary functions
function foo() {
console.log(this);
}
foo()
Copy the code
Return window object
constructors
// The constructor this refers to the instance object p
function Person() {}
// The methods inside the prototype object also point to the instance object
Person.prototype.say = function() {
console.log(this);
}
var p = new Person()
p.say(); // Person {}
Copy the code
3. Object methods
var person = {
namer: 'Joe'.sayNmae: function() {
console.log(this.namer);
}
}
person.sayNmae(); / / zhang SAN
Copy the code
When a function is called as a method of an object, this in the function is that object
However, if the object is assigned a global variable, this points to the window object
var namer = 'bill'
var p = person.sayNmae;
p(); / / li si
Copy the code
4. Event binding functions
var btn = document.querySelector('button')
btn.onclick = function() {
console.log(this); //
}
Copy the code
In the event binding function, this refers to the bound event, so click the button to output the Button event
5. Timer function
setTimeout(function() {
console.log(this);
}, 500)
Copy the code
Print the Window object after 0.5 seconds
Execute the function immediately
(function() {
console.log(this); }) ()Copy the code
The immediate function is also an ordinary function in nature, whose this naturally points to the Window object
Arrow function
The arrow function in ES6 has no execution context of its own, so the arrow function’s this is its outer function’s this
Note:
- It’s in the outer function of the arrow function
this
Is not in the objectthis
- If there is no outer function, then
this
The default point towindow
object
var namer = 'bill'
var person = {
namer: 'Joe',}// Arrow function
var sayNmae = () = > console.log(this.namer)
sayNmae(); / / li si 7
// Add arrow function
person.sayNmae = sayNmae
// Still access global variables
person.sayNmae(); / / li si
Copy the code
In the arrow function, this refers to the context in which the arrow function is defined. In both of the above calls, this refers to the window object because the arrow function is defined in window
3. Change inside the functionthis
The point to
Js provides several methods to change the direction of this inside a function. There are three common methods:
call()
apply()
apply()
3.1 call()
methods
The call() method does two things: change the direction of this and call the function
var person = {
name: 'Joe'
}
function foo(a, b) {
console.log(this);
console.log(a + b);
}
foo.call(person, 1.2) // {name: 'zhang SAN'} 3
Copy the code
This is already pointing to the Person object
The main purpose of the Call method is to implement inheritance
3.2 apply()
methods
func.apply(thisAry, [argsArray])
Copy the code
thisAry
: specified when the func function is runthis
valueargsArray
: The value passed must be contained in the arrayapply()
The array is automatically converted to the numeric type we need
var person = {
name: 'Joe'
}
function foo(a, b) {
console.log(this);
console.log(a + b);
}
foo.apply(person, [1.2]) // {name: 'zhang SAN'} 3
Copy the code
Apply () is often associated with arrays, such as extracting the maximum and minimum values of an array with built-in array objects
Math.max()
Specifies that a single value must be passed in
var max = Math.max(1.20.3.10.15)
console.log(max);
Copy the code
We use Apply to split the array into individual values and pass them to Max to find the maximum value of the array
var arr = [11.20.3.10.15]
var max = Math.max.apply(Math, arr)
console.log(max); / / 20
var min = Math.min.apply(Math, arr)
console.log(min); / / 3
Copy the code
Point this in Apply to the function’s caller, Math
3.3 bind()
methods
The best thing about bind() is that it doesn’t call a function, just like call()
func.bind(thisAry, arg1, arg2, ...) ;Copy the code
thisAry
: specifies when the func function is runthis
valuearg1
,arg2
: Passes a single parameter
var person = {
name: 'Joe'
}
function foo(a, b) {
console.log(this);
console.log(a + b);
}
var f = foo.bind(person, 1.2)
f(); // {name: 'zhang SAN'} 3
Copy the code
You can use bind if you don’t need to call a function immediately, but want to change the reference to this inside the function
Bind is also the most commonly used of the three methods
4,this
There is a drawback
Bug: This in a nested function does not inherit this in an outer function
var namer = 'bill'
var obj = {
namer: 'Joe'.show: function() {
console.log(this.namer); / / zhang SAN
function foo() {
console.log(this.namer); / / li si
}
foo()
}
}
obj.say()
Copy the code
As you can see, the show method’s this refers to its object obj, and the foo function’s this does not inherit its external function show’s this, but the global object Window
There are two solutions:
- Declare a variable to save
this
- Using the arrow function
Method one “declare a variable that to hold this
var namer = 'bill'
var obj = {
namer: 'Joe'.show: function() {
console.log(this.namer); / / zhang SAN
/ / save this
var that = this
function foo() {
console.log(that.namer); / / zhang SAN
}
foo()
}
}
obj.say()
Copy the code
Method two: arrow function
The arrow function has no context of its own, so where the arrow function is defined, its context is there, so where does this point to
var namer = 'bill'
var obj = {
namer: 'Joe'.say: function() {
console.log(this.namer); / / zhang SAN
var foo = () = > {
console.log(this.namer); / / zhang SAN
}
foo()
}
}
obj.say()
Copy the code
Applet: When we click this button, immediately disable this button, 2 seconds later to enable it
When you think about delays, the first thing that comes to mind is using setTimeout or setInterval
var btn = document.querySelector('button')
// Click the button
btn.onclick = function() {
// The event binding function, this refers to the bound event BTN
this.disabled = true; // Disable the button first
setTimeout(function() {
// This refers to the window object
this.disabled = false;
}, 2000)}Copy the code
According to our above analysis, this way is absolutely GG, can not achieve the effect
The event object referred to by this in the event function is disabled after the button is clicked; The problem arises when this in the delay function refers to the window object
So we need to access the event object in the delay function. There are four ways:
- Direct use of
btn
The event object - save
this
- Using the arrow function
- using
bind
Modify thethis
Point to the
Method 1: Use the BTN event object
var btn = document.querySelector('button')
btn.onclick = function() {
this.disabled = true;
var that = this
setTimeout(function() {
btn.disabled = false;
}, 2000)}Copy the code
Disadvantages: Event name changes, the following will be modified, very inconvenient, not recommended
Method 2: Savethis
btn.onclick = function() {
this.disabled = true;
var that = this / / save this
setTimeout(function() {
that.disabled = false
}, 2000)}Copy the code
Disadvantages: Need to open up new memory space to store that, increase the code
Method 3: Arrow function
btn.onclick = function() {
this.disabled = true;
// Arrow function
setTimeout(() = > {
this.disabled = false
}, 1000)}Copy the code
The arrow function defined in the event click function, whose this points to the event object where its context resides
Method four: usebind
Modify thethis
Point to the
Bind has two main features: it changes the this pointer, and it doesn’t call a function
Because all we need to do is change the this pointer in the delay function, we don’t need to call the function, call the function and let the delay function take care of itself
btn.onclick = function() {
this.disabled = true;
setTimeout(function() {
this.disabled = false
}.bind(this), 2000)}Copy the code
conclusion
- In non-strict mode, of the function
this
Point to thewindow
Object; In strict mode, the functionthis
The value ofundefined
call
andapply
Will execute the function itself,bind
It does not. It returns a new function that has been bound to a new onethis
- Arrow functions are like parasites, defined in their context
this
Who is to - In the inheritance function
this
Does not inherit its outer functionthis
value