Keyword this
is a fundamental concept and is no stranger to JavaScript, and according to her it is something misleading and mistaken in this language, this article yourself and you will learn how to Use this
correctly in various situations, including sensitive cases, where this
is difficult to grasp.
So What is This?
Basically, we use this
same way that we use personal pronouns , for example both English and Vietnamese as follows:
- English : “John is running fast because he is trying to catch the train.”
- Vietnamese : “Huy is learning English, he’s trying very hard.”
Can you find yourself using the pronoun he and him in the above two sentences? Obviously I can completely rewrite like this:
- English : “John is running fast because, Joh is trying to catch the train.”
- Vietnamese : “Huy is learning English, Huy is trying very hard.”
However, in spoken and written literature, not many people and they rarely repeat the name of the character John / Huy , (of course it is not wrong, but it is a bit difficult to hear and if you keep using it). Using such a name is hard to hear.)
=> So short-pointers this
in JavaScript is used to represent 1 Object (Object), Object that is the subject of context, or subject of code is run.
For example :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | const Person = { ho:'Nguyen', ten:'Tam', ghepHoTen:function(){ // mình sử dụng cách bình thường để lấy value trong 1 Object // tên Object toán tử '.' rồi đến name của object cần lấy value console.log('Họ và tên',Person.ho + " " + Person.ten); // Mình sử dụng con trỏ this, tương tự như việc dùng he/anh ấy console.log('Họ và tên',this.ho + " " + this.ten); } } Person.ghepHoTen(); |
You can run, and display the same results, although for new people, using Person.ho will be more intuitive and easier to understand than using this
cursor as the number 2.
However, if your Project after a period of development, and that Project also a few people join but not just you, and the Person
above example is a Local variable (local) is create and reside in a certain function , and a certain function also has a local variable with the same name as Person
, and there still exists one more Global variable (global), the problem has become troublesome already: 3 .
To avoid making us miserable, miserable, let us use this
keyword, not only because it is easy to see, but also the clarity and accuracy in the code, like the pronoun pronouns in communication.
Just like he , he refers to the nouns in the example, this
keyword in JavaScript will also be used to refer to the Object whose function (where this
is used) is bound.
Keyword this
is not the only reference that contains Object value (value) of that object.
The basics of this
First of all, you need to understand that all functions have Property , just like every other Object . When executing that fuction , it will have Property this
containing the item of an Object that is calling this function .
Simply put, I have one tentatively called functionA function, the pointer this
contains the items referred to functionA Object, and it is also possible through this
to get the other items in the Object call functionA.
Note that, if we use strict mode , this
will be undefined in the Global functions .
For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 | "use strict"; const ObjA ={ ho:'Nguyễn', ten:'Tâm' } function functionA(){ console.log(this.ObjA) } functionA(); |
If
this
is used inside afunction
(let’s call it functionA ) then it will contain theObject
item
called functionA . We needthis
to access back to getObject
method
andProperty
call functionA .
There are a few notes about this
as follows:
this
is the context of where the function contains the keywordthis
calls.- There are two types of context for
this
keyword: Object contains the method called or Global , nothing more. - So when you meet
this
you don’t care about what it is? but only care about where the function call is stored.
Review the example to understand more about this
1 2 3 4 5 6 7 8 9 | const Person = { ho:'Nguyen', ten:'Tam', ghepHoTen:function(){ console.log('Họ và tên',this.ho + " " + this.ten); } } Person.ghepHoTen(); |
The example above I use this
pointer used in the method ghepHoTen, and this method is defined in the Object Person, so this
will have an item
of Object Person.
I have more examples of this
for jQuery :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <!DOCTYPE html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script> $(document).ready(function(){ // mình sẽ không nói gì đến jQuery nữa nhé // quan tâm từ đây nè $ ("button").click (function (event) { console.log ($ (this).prop("name")); }); // kết thúc, những thứ khác bạn hãy tự tìm hiểu }); </script> </head> <body> <button name="ahihidongok">Add</button> </body> </html> |
For the jQuery example above, note a few points:
<button name="ahihidongok">Add</button>
This is an element of the DOM , so it is an Object .$ ("button")
, we see thisbutton
is included in the function of jQuery$()
, so now it has become Object jQuery .- jQuery function
$()
essentially anonymous function (function not name), which is the anonymous function, there is no public Object call it. Without any Object ,this
will have no context to point to. - However,
$(this)
still has the value of the jQuery Objectbutton
because the authors of the jQuery library have always defined that$(this)
will be bound to the Object calling the click () method .
This is also quite interesting, I have to let you guys try it out:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <!DOCTYPE html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script> $(document).ready(function(){ // mình sẽ không nói gì đến jQuery nữa nhé // quan tâm từ đây nè $ ("button").click (function (event) { console.log ($ (this).prop("name")); }); // kết thúc, những thứ khác bạn hãy tự tìm hiểu }); </script> </head> <body> <button name="ahihidongok_1">Add 1</button> <button name="ahihidongok_2">Add 2</button> <button name="ahihidongok_3">Add 3</button> <button name="ahihidongok_4">Add 4</button> </body> </html> |
Run the code yourself and see the results , guys, quite useful, ahihi
Additional note
If you’ve come this far, and understand the basics of pointers this
then you will find that:
this
of 1 function will not begin any item at all until 1 Object function call containsthis
inside (I call it functionB offline).
1 2 3 4 5 6 7 8 9 10 11 | const Person = { ho:'Nguyen', ten:'Tam', ghepHoTen:function(){ console.log('Họ và tên',this.ho + " " + this.ten); } } // cái này mình không biết lấy ví dụ thế nào để dễ hiểu hơn, nhưng nó như thế này. // Person không gọi method ghepHoTen, các bạn console.log sẽ cho ra kết quả. console.log(Person) |
- Most of
this
contains Object ‘s item that calls the function , but most of the time.
Use this
at the global scope
In the global scope, when code is executed in the browser, all variables (variables) and functions of type Global are defined in the Object window
.
Therefore, when using this
in the Global form, it will point to (and carry the value) of the Object window
(this is no longer true in strict mode as mentioned above).
Note: The Object window
is an administrator for all JavaScript applications that run on the web .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | var firstName = "Nhung", lastName = "Nguyễn Hồng"; function showFullName () { // Lưu ý: Đây là 1 hàm được định nghĩa trong môi trường global, cùng môi trường với variables "firstName" và "lastName". // Do đó, "this" ở trong dây sẽ trỏ (và mang giá trị) của object "window" console.log (this.firstName + " " + this.lastName); } var person = { firstName :"Hà", lastName :"Trần Thu", showFullName:function () { // Lưu ý: Đây là 1 hàm được định nghĩa trong 1 object (tên là "person") // object "person" này sẽ gọi hàm "showFullName" khi có nhu cầu // do đó, "this" ở trong đây sẽ trỏ và mang giá trị của object "person" // chứ ko phải object "window" như ở trên. console.log (this.firstName + " " + this.lastName); } } showFullName (); // Nhung Nguyễn Hồng // this hay window đều được, mình có giải thích ở trên rồi nhé. window.showFullName (); // Nhung Nguyễn Hồng person.showFullName (); // Hà Trần Thu |
Some cases are easy to confuse about this
When entering the actual project, there are cases where this
is difficult to know where it points, in this section, you and your friends learn such situations and how to handle them accordingly.
Change context
A bit of “context” before continuing:
As I said above the context is (context), similar to the following sentence:
Tâm là một lập trình viên, anh ấy là người Việt Nam.
Back to level 1 a little bit, identify the sentence above, the Mind is the subject of the sentence, and we go to grade 11 to know more that the context is the Heart because the whole sentence at this time is focused Talk about mind .
even the pronoun he points to Tam .
And like we can use the semicolon (“;”) to change the subject of a sentence, we can convert the current context of the first object to a second object by calling the function corresponding to second statue.
For example :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | const PersonA = { ho:'Nguyen', ten:'Tam', ghepHoTen:function(){ console.log(this.ho +' '+ this.ten); } } const PersonB = { ho:'Đức', ten:'Trọng' } // "Ngữ cảnh", khi chúng ta gọi ghepHoTen là đối tượng personA // khi chúng ta gọi ghepHoTen cho đối tượng này. Và "this" trong // function này sẽ có giá trị của đối tượng personA. console.log(PersonA.ghepHoTen()) // Chúng ta có thể sử dụng function apply để gán giá trị "this" một cách rõ ràng hơn // trong function apply, "this" sẽ có giá trị của bất cứ thứ gì gọi functon this. Vì thế: console.log(PersonA.ghepHoTen.apply(PersonB)); // Lưu ý mặc dù trông thì có vẻ như Object PersonA gọi functon ghepHoTen // Nhưng do dùng method apply rồi, nên về thực tế là nó đã chuyển sang gọi thông qua object PersonB |
Using this
in the function is passed as a callback
Suppose, I want to click on a button , I will call the ghepHoTen function of Person . Extremely simple, we just pass the function ghepHoTen as a callback for the click function is done.
1 2 3 4 5 6 7 8 9 10 11 12 13 | const Person = { ho:'Nguyen', ten:'Tam', ghepHoTen:function(){ console.log(this.ho +' '+ this.ten); } } //Ở đây this sẽ là object Person Person.ghepHoTen(); //Nguyen Tam $('button').click(Person.ghepHoTen); //ghepHoTen truyền vào như callback |
However, the result will not be as expected, I also explained the above reason with the jQuery example. The object here will be the button
itself, not the Person
.
Fix it by using the anonymous function , or using the bind function to change the context function that is passed.
Replace the following example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | const Person = { ho:'Nguyen', ten:'Tam', ghepHoTen:function(){ console.log(this.ho +' '+ this.ten); } } //Ở đây this sẽ là object Person Person.ghepHoTen(); //Nguyen Tam $('button').click(Person.ghepHoTen); //ghepHoTen truyền vào như callback // anonymous function, dùng jQuery thì mình nghĩ cách này sẽ dùng mặc định rồi $('button').click(function(){Person.ghepHoTen()}); // Xem coi nó trỏ đến Object button như mình nói không nhé $('button').click(function(){console.log(this)}); // sử dụng bind $('button').click(Person.ghepHoTen.bind(Person)); //this ở đây vẫn là object Person |
Use this
inside the closure
Another case easy to be misunderstood, that when this
is used in a nested function in a different function (a closure). Note that closures cannot access this
of the outer function (the outer function ).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | const Person = { ten:'Tam', tuoi: [20,21,22,23,24,25], ghepHoTen:function(){ this.tuoi.forEach(function(value){ // trong này là 1 anonymous function được lồng trong 1 function, // do vậy nó không truy cập được this của function bên ngooài. console.log(this.ten +' '+ value); }) } } Person.ghepHoTen(); |
this
inner anonymous function cannot access this
of the external function , so it will be assigned to the Object window
(if not using strict mode
).
Replace the following example:
1 2 3 4 5 6 7 8 9 10 11 12 13 | const Person = { ten:'Tam', tuoi: [20,21,22,23,24,25], ghepHoTen:function(){ var that = this; //Gán giá trị this vào biến that this.tuoi.map(function(value){ console.log(that.ten +' '+ value); }) } } Person.ghepHoTen(); |
In this case, the usual solution is to create a variable to assign this
value to, and access that value in the anonymous function , here I use:
var that = this; //Gán giá trị this vào biến that
If you read a lot of sample code , you will find that JavaScript programmers like to pass this
to a variable called that
. This naming method doesn’t carry a lot of information (though it may sound awkward), so it is advisable to use a more descriptive name, such as theUserObj
.
var theUserObj = this; //Gán giá trị this vào biến theUserObj
When the function is assigned to a variable
If we assign a function to another variable , the context will also be changed. For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | const ho = 'Duc'; const ten = 'Thanh'; const Person = { ho:'Nguyen', ten:'Tam', ghepHoTen:function(){ console.log(this.ho +' '+ this.ten); } } // in kết quả kiểm tra context của this trong function ghepHoTen Person.ghepHoTen(); // gán function ghepHoTen cho 1 variable const PersonA = Person.ghepHoTen; // context đã bị thay đổi, mình cần là kết quả 'Nguyen Tam' PersonA(); |
To solve, we also use the bind function , too simple is not it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | const ho = 'Duc'; const ten = 'Thanh'; const Person = { ho:'Nguyen', ten:'Tam', ghepHoTen:function(){ console.log(this.ho +' '+ this.ten); } } // in kết quả kiểm tra context của this trong function ghepHoTen Person.ghepHoTen(); // gán function ghepHoTen cho 1 variable const PersonA = Person.ghepHoTen; // context đã bị thay đổi, mình cần là kết quả 'Nguyen Tam' PersonA(); // dùng bind để sửa lại context const PersonB = Person.ghepHoTen.bind(Person) // context đã cập nhật là Person, mình có kết quả như cũ 'Nguyen Tam' PersonB() |
When this
used in borrowing method
Borrowing method is quite common in JavaScript , borrowing method helps us save time to develop features that have been developed before, our job is simply take and reuse. .
For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // Chúng ta có 2 Object, 1 Object có function computeAvg() và 1 Object thì không // Chúng ta sẽ thực hiện mượn function này var gameController = { scores: [10, 15, 20], avgScore: null, players: [ {name: "Tommy", playerID: 987, age: 23}, {name: "Pau", playerID: 87, age: 33} ] }; var appController = { scores: [30, 40, 50], avgScore: null, computeAvg: function () { var sumOfScores = this.scores.reduce (function (prev, cur, index, array) { return prev + cur; }); this.avgScore = sumOfScores / this.scores.length; } } |
We want to borrow the computeAvg () method of Object appController to calculate the average score for the Object gameController. To do this, we need to change the context of the computeAvg () method to Object gameController at runtime, the apply () method in JavaScript will help us to do this:
1 2 3 | appController.computeAvg.apply(gameController); console.log(gameController.avgScore); |
So we just made borrowing method and changed context with function apply .
Conclude
Hopefully the article above its helped you understand more about pointers this
, for the function (bind, apply, and call) I will try to write a new post to explain more clearly how to use them, but hope That in my article you can understand and use them a little bit.
Always remember that
this
points to the Object containing the called method or the Globalwindow
, and nothing else.
Any comments or suggestions please comment below.
The article has references from the source:
https://travisnguyen.net/general/2017/09/27/javascript-hieu-ve-this/
https://viblo.asia/p/this-trong-javascript-gAm5ywe8Zdb
https://kipalog.com/posts/Con-tro-this-in-Javascript
https://toidicodedao.com/2016/01/26/series-javascript-sida-luan-ban-ve-cai-dit-this-in-javascript/