Talking about this in Javascript again

  • 2021-07-01 06:01:13
  • OfStack

I have a specious feeling about this in Javascript. Today, I suddenly feel enlightened. I hereby record 1.

Let's look at a chestnut first:


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>this Use of </title>
<script type="text/javascript">
var Car,tesla;
Car=function () {
this.start=function(){
console.log('car started');
};
this.turnKye=function () {
var carKey=document.getElementById('car_key');
carKey.onclick=function () {
this.start(); 
};
}
return this;
}
tesla=new Car();
tesla.turnKye();
</script>
</head>
<body>
<input type="button" id="car_key" value="test" />
</body>
</html> 

At first glance, there is nothing wrong with this code, but the wrong understanding of this eventually leads to the wrong result. We bind the click event on top of the element car_key, and think that nesting the click event in the class of car allows this dom element to access the this context of car. This method seems reasonable, but unfortunately it doesn't work.

In Javascript, the this keyword always points to the owner of the scope being executed.

Please try to figure out the above sentence carefully. As we know, the function call creates a new scope, the onclick event is triggered at 1 point, and this points to the dom element instead of the Car class.

So what can we do to make it work properly? We usually assign this to a local free variable (such as that, _ this, self, me, etc., which are embodied in many frameworks) to avoid the problem caused by scope. Here, we use local variables to override the previous method:


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>this Use of </title>
</head>
<body>
<input type="button" id="car_key" value="test" />
<script type="text/javascript">
var Car,tesla;
Car=function () {
this.start=function(){
console.log('car started');
};
this.turnKye=function () {
var that=this;
var carKey=document.getElementById('car_key');
carKey.onclick=function () {
that.start(); 
};
}
return this;
}
tesla=new Car();
tesla.turnKye();
</script>
</body>
</html> 

Since that is a free variable, the start of the onclick event does not cause it to be redefined.

If you are familiar with ES6, you can use the fat arrow symbol, which is simpler and easier to understand, as follows:


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>this Use of </title>
</head>
<body>
<input type="button" id="car_key" value="test" />
<script type="text/javascript">
var Car,tesla;
Car=function () {
this.start=function(){
console.log('car started');
};
this.turnKye=function () {
//var that=this;
var carKey=document.getElementById('car_key');
//carKey.onclick=function () {
// that.start(); 
//};
carKey.onclick=()=>this.start();
}
return this;
}
tesla=new Car();
tesla.turnKye();
</script>
</body>
</html> 

Of course, we can also use the method of binding functions to solve this problem: as follows


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>this Use of </title>
</head>
<body>
<input type="button" id="car_key" value="test" />
<script type="text/javascript">
var Car,tesla;
Car=function () {
this.start=function(){
console.log('car started');
};
var click=function(){
this.start(); 
}
this.turnKye=function () {
//var that=this;
var carKey=document.getElementById('car_key');
carKey.onclick=click.bind(this);
}
return this;
}
tesla=new Car();
tesla.turnKye();
</script>
</body>
</html> 

In fact, these pits encountered when learning React and binding events only knew how to write them at that time, but I don't know what happened. Today, I suddenly feel suddenly enlightened. I hope it will be helpful to everyone.


Related articles: