Understanding this keyword for JavaScript

  • 2021-06-29 09:36:06
  • OfStack

Conceptual overview this

When a function is created, a keyword, this, is created (in the background), linking it to an object in which the function operates.In other words, the keyword this can be used in a function as a reference to an object whose property or method is the function.

Let's look at this object:


<!DOCTYPE html><html lang="en"><body><script> 
var cody = { 
living:true, 
age:23, 
gender:'male', 
getGender:function(){return cody.gender;} 
}; 
console.log(cody.getGender()); // logs 'male' 
</script></body></html>

Notice in the function getGender that since inside the cody object, we can get the gender attribute (that is, cody.gender) from.You can also use this to get the cody object, because this is pointing to the cody object.


<!DOCTYPE html><html lang="en"><body><script> 
var cody = { 
living:true, 
age:23, 
gender:'male', 
getGender:function(){return this.gender;} 
}; 
console.log(cody.getGender()); // logs 'male' 
</script></body></html>

this in this.gender points to the cody object, while the getGender function can manipulate the cody object.

The topic about this can be a bit confusing, but it doesn't have to be.Just remember that in general, this points to the object that contains the function, not the function itself (with the exception of the keywords new or call () and apply ()).

Important Tips

-The keyword this is like any other variable except that you cannot change it.

- Unlike other parameters and variables passed to the function, this is a keyword (not a property) in the object calling the function.

How do I determine the value of this?

this passes to all functions, and its value depends on when the function is called when it runs.Note here, because this is a very special place you need to remember.

In the code below, the myObject object has an attribute, sayFoo, which points to the function sayFoo.When the sayFoo function is called locally, this points to the window object.When myObject calls the function, this points to myObject.

Because myObject has a property called foo, it is used here.


<!DOCTYPE html><html lang="en"><body><script> 
var foo = 'foo'; 
var myObject = {foo: 'I am myObject.foo'}; 
var sayFoo = function() { 
console.log(this['foo']); 
}; 
// give myObject a sayFoo property and have it point to sayFoo function 
myObject.sayFoo = sayFoo; 
myObject.sayFoo(); // logs 'I am myObject.foo' 12 
sayFoo(); // logs 'foo' 
</script></body></html>

Clearly, the value of this depends on when the function is called.myObject.sayFoo and sayFoo both point to the same function, but sayFoo () calls in different contexts and this values are different.Here is a similar code, the head object (window) is explicitly used, and I hope it will be useful to you.


<!DOCTYPE html><html lang="en"><body><script> 
window.foo = 'foo'; 
window.myObject = {foo: 'I am myObject.foo'}; 
window.sayFoo = function() { ! console.log(this.foo); }; 
window.myObject.sayFoo = window.sayFoo; 
window.myObject.sayFoo(); 
window.sayFoo(); 
</script></body></html>

Make sure that when you have multiple references to the same function, you know that the value of this changes depending on the context in which the function is called.

Important Tips

- All variables and parameters except this are in the static variable range (lexical scope).

this points to an head object within an embedded function

You may want to know what happens when this is used in a function embedded in another function.Unfortunately in ECMA 3, this does not follow the rule, it does not point to the object to which the function belongs, but to the head object (the browser's window object).

In the code below, this in func2 and func3 no longer points to myObject, but to an head object.


<!DOCTYPE html><html lang="en"><body><script> 
var myObject = { 
func1:function() { 
console.log(this); //logs myObject 
varfunc2=function() { 
console.log(this); //logs window, and will do so from this point on 
varfunc3=function() { 
console.log(this); //logs window, as it's the head object 
}(); 
}(); 
} 
}; 
myObject.func1(); 
</script></body></html>

However, in ECMAScript 5, this issue will be corrected.Now you should be aware of this problem, especially when you pass the value of one function to another.

Look at the code below and pass an anonymous function to foo.func1. When an anonymous function is called in foo.func1 (the function is nested in another function), this in the anonymous function will point to the head object.


<!DOCTYPE html><html lang="en"><body><script> 
var foo = { 
func1:function(bar){ 
bar(); //logs window, not foo 
console.log(this);//the this keyword here will be a reference to foo object 
} 
}; 
foo.func1(function(){console.log(this)}); 
</script></body></html>

Now you won't forget that if a function containing this is in another function, or called by another function, the value of this will point to the head object (again, this will be fixed in ECMAScript 5).

Solving problems with nested functions

In order not to lose the value of this, you can use a scope chain (scope chain) in the parent function to save a reference to this.The code below uses a variable called that whose scope allows us to better preserve the function context.


<!DOCTYPE html><html lang="en"><body><script> 
var myObject = { 
myProperty:'Icanseethelight', 
myMethod:function() { 
var that=this; //store a reference to this (i.e.myObject) in myMethod scope varhelperFunctionfunction(){//childfunction 
var helperFunction function() { //childfunction 
//logs 'I can see the light' via scope chain because that=this 
console.log(that.myProperty); //logs 'I can see the light' 
console.log(this); // logs window object, if we don't use "that" 
}(); 
} 
} 
myObject.myMethod(); // invoke myMethod 
</script></body></html>

Controlling the value of this

The value of this usually depends on the context in which the function is called (unless the keyword new is used, which you will introduce later), but you can use apply () or call () to specify the object that this points to when a function is triggered to change/control the value of this.Using these two methods is like saying, "Hey, call the X function, but let the Z object do the this value."By doing so, the default value of JavaScript, this, will be changed.

Next, we create an object and a function, and then we trigger the function with call (), so the this in the function points to myOjbect.this in the myFunction function manipulates the myObject object instead of the head object, so we change the object this points to in myFunction.


<!DOCTYPE html><html lang="en"><body><script> 
var myObject = {}; 
var myFunction = function(param1, param2) { 
//setviacall()'this'points to my Object when function is invoked 
this.foo = param1; 
this.bar = param2; 
console.log(this); //logs Object{foo = 'foo', bar = 'bar'} 
}; 
myFunction.call(myObject, 'foo', 'bar'); // invoke function, set this value to myObject 
console.log(myObject) // logs Object {foo = 'foo', bar = 'bar'} 
</script></body></html>

In the example above, we used call (), apply () can also be used in the same way, but the difference between them is how the parameters are passed to the function.With call (), parameters are separated by commas, and with apply (), parameters are passed in an array.The following is the same code, but with apply ().


<!DOCTYPE html><html lang="en"><body><script> 
var myObject = {}; 
var myFunction = function(param1, param2) { 
//set via apply(), this points to my Object when function is invoked 
this.foo=param1; 
this.bar=param2; 
console.log(this); // logs Object{foo='foo', bar='bar'} 
}; 
myFunction.apply(myObject, ['foo', 'bar']); // invoke function, set this value 
console.log(myObject); // logs Object {foo = 'foo', bar = 'bar'} 
</script></body></html>

Using this in a custom constructor

When a function is triggered with the keyword new, the value of this is declared in the constructor to point to the instance itself.In other words, in a constructor, we can use this to specify objects before they are actually created.In this way, changes in the this value are similar to call () or apply ().

Next, we construct a constructor, Person, that points to the object created.When an Person object is created, this points to it and places the property name inside the object, with the value of the parameter passed to the constructor (name).


<!DOCTYPE html><html lang="en"><body><script> 
var Person = function(name) { 
this.name = name || 'johndoe'; // this will refer to the instanc ecreated 
} 
var cody = new Person('Cody Lindley'); // create an instance, based on Person constructor 
console.log(cody.name); // logs 'Cody Lindley' 
</script></body></html>

In this way, when the constructor is triggered with the keyword new, this points to the "object to be created".So if we don't use the keyword new, the value of this will point to the context in which Person was triggered -- then the head object.Let's look at the code below.


<!DOCTYPE html><html lang="en"><body><script> 
var cody = { 
living:true, 
age:23, 
gender:'male', 
getGender:function(){return this.gender;} 
}; 
console.log(cody.getGender()); // logs 'male' 
</script></body></html>
0

this points to a construction instance within the prototype method

When a method is an prototype property of a constructor, this in this method points to an instance of the trigger method.Here, we have a constructor for Person (), which requires the full name of person (full name). To get the full name (full name), we added an whatIsMyFullName method to Person.prototype, which is inherited by all Person instances.this in this method points to the instance (and its properties) that triggered the method.

Below I create two Person objects (cody and lisa), and the this contained in the inherited whatIsMyFullName method points to this instance.


<!DOCTYPE html><html lang="en"><body><script> 
var cody = { 
living:true, 
age:23, 
gender:'male', 
getGender:function(){return this.gender;} 
}; 
console.log(cody.getGender()); // logs 'male' 
</script></body></html>
1

Using this in a method within the prototype object, this points to an instance.If the instance does not contain attributes, the prototype lookup begins.

Tips

- If the object this points to does not contain the attribute you want to find, then the rule that applies to any attribute applies here as well, that is, the attribute will be "found" along the prototype chain (prototype chain).So in our example, if the fullName attribute is not included in the instance, fullName looks for Person.prototype.fullName, followed by Object.prototype.fullName.


Related articles: