What is this in JavaScript بالعربي
دليلك الشامل لفهم كلمة this في الجافاسكريبت
بعد الانتهاء من القراءة ستكون قادر على:
✅ الفهم الكامل لكلمة this
في الجافاسكريبت
✅ معرفة اهمية call
في this
context
✅ معرفة أهمية apply
في this
context
✅ معرفة أهمية bind
في this
context
✅ نظرة سريعة على اهمية ال Arrow function في this
context
المقدمة:
هنتكلم عن حبة غموض في استخدام this
في الجافاسكريبت ونبدأ نزيل الغموض ده واحده واحده ان شاء الله
let person = {
name: 'Osama',
sing: function() {
return `${this.name} sings la la la.`;
}
};
console.log(person.sing()); // Output: Osama sings la la la.
في المثال ده this.name
طبعت Osama اللي هي Property لل Object person
طيب لو جربنا نأ assign ال function sing ل variable تاني زي كدا ايه اللي هيحصل؟
const pSing = person.sing;
console.log(pSing()); // Output: sings la la la.
هنلاقيها طلعت this.name ب String فاضي، يا ترى ايه السبب مع انها نفس ال Function؟
طيب تعالو نشوف مثال تاني:
class Person {
constructor(name){
this.name = name;
}
sing(){
console.log(`${this.name} sings la la la.`)
}
}
const person = new Person("Osama");
console.log(person.sing()); // Output: Osama sings la la la.
طيب لو جربنا نأ assign ال sing method ل variable تاني زي كدا ايه اللي هيحصل؟
const pSing = person.sing;
console.log(pSing()); // Output: Uncaught TypeError: Cannot read properties of undefined (reading 'name')
يا ترى ايه السبب مع انها نفس ال Function؟ وليه مش String فاضي زي في حالة ال Object literal؟
ونفتكر التويته دي مع بعض 😂
الدرس الأول:
يعني ايه؟
يعني لو عملت Function اسمها greet في الكود بتاعك انت في الأصل بتعملها في ال global object
function greet(){
console.log('hi');
}
يعني اكنك بالظبط كاتب
window.greet = function(){
console.log('hi');
}
الدرس الثاني:
نستنتج من هنا قاعدة مهمة جداً للتعامل مع this
function whatIsThis(){
console.log('this is: ', this);
}
whatIsThis(); // Output: this is: `window object`
window.whatIsThis(); // Output: this is: `window object`
في المثال ده this عادت على ال window object لأن زي ما اتفقنا When you call function on nothing... You call it on the 'global object'.
طيب ناخد مثال تاني:
const obj = {
whatIsThis:whatIsThis
}
obj.whatIsThis() // Output: this is `obj object`
طيب نرجع للمثال اللي اخدناه فوق:
let person = {
name: 'Osama',
sing: function() {
return `${this.name} sings la la la.`;
}
};
console.log(person.sing()); // Output: Osama sings la la la.
const s = person.sing;
console.log(s()) // Output: sings la la la.
ايه تفسير الكود ده؟ وليه طبع string فاضي مكان ال this.name؟
اول حاجه هو خد نسخة من ال function اللي هي sing فبقى ال variable s عبارة عن:
const s = function(){
return `${this.name} sings la la la.`;
}
وهنا this بقت عايدة على ال window object، وبعدين راح يدور على name في ال window object ملاقاش
> window.name
< ''
عشان كدا طبع string فاضي مكان ال this.name
وبكدا نكون فهمنا ال Rule بتاعتنا
الدرس الثالث:
في behavior مختلف شوية لما تستخدم this في الكلاس
class Person {
constructor(name){
this.name = name;
}
sing(){
console.log(`${this.name} sings la la la.`)
}
}
const person = new Person("Osama");
console.log(person.sing()); // Output: Osama sings la la la.
const pSing = person.sing;
console.log(pSing()); // Output: Uncaught TypeError: Cannot read properties of undefined (reading 'name')
يا ترى ليه بقى في error لما استخدمنا ال method بتاعة الكلاس في variable جديد؟
هنا بيحصل حاجة اسمها losing of this context بيحاول يوصل ل sing في الكلاس بس بتكون undefined لان الكلاس دايماً بيكون في ال strict mode
const pSing = person.sing;
pSing(); // TypeError because the 'sing' method tries to access 'this.name', but 'this' is undefined in strict mode.
الدرس الخامس:
امتى بنسخدم call؟
بنستخدم call
لما نعوز نغير قيمة ال this
مثال:
const person = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
const person1 = {
firstName:"John",
lastName: "Doe"
}
const person2 = {
firstName:"Mary",
lastName: "Doe"
}
// This will return "John Doe":
person.fullName.call(person1);
طيب على كده احنا ممكن نحل مشكلة ال class اللي فاتت لما كان بيطبع error صحيح؟
class Person {
constructor(name){
this.name = name;
}
sing(){
console.log(`${this.name} sings la la la.`)
}
}
const person = new Person("Osama");
console.log(person.sing()); // Output: Osama sings la la la.
const pSing = person.sing;
console.log(pSing.call(person)); // Output: Osama sings la la la.
ممكن call تاخد parameters بالطريقة دي:
class Person {
constructor(name){
this.name = name;
}
sing(song){
console.log(`${this.name} sings ${song}`)
}
}
const pSing = person.sing;
console.log(pSing.call(person, 'laghbatita')); // Output: Osama sings laghbatita.
الدرس السادس:
تعالو نتكلم عن apply، في الحقيقة apply زي call بالظبط بنقدر نغير بيها قيمة this
ولكن بتاخد ال arguments على هيئة array like
عندنا مثال مشهور بنستخدمه كل يوم وهو لو عاوزين نجيب اكبر رقم في الارقام في ال array بنعمل الآتي
const numbers = [2,36,73,622];
const max = Math.max(...numbers)
console.log(max); // Output: 622
هنا ال spread operator وزعت كل الارقام عشان تكون كل واحده في arguments
يعني المفروض هيا عملت كدا...
const max = Math.max(2,36,73,622)
console.log(); // Output: 622
لو عاوزين نستخدم apply هنعمل الآتي
const numbers = [2,36,73,622];
const max = Math.max.apply(null,numbers)
console.log(); // Output: 622
هنا خلينا this ب null لان قيمتها مش مهمه واستخدمنا apply عشان تعمل spread لل arguments
الدرس السابع:
امتى بنستخدم bind؟ لو هنعمل call او apply كزا مره في الكود ومش عاوزين تكرار؟ ممكن نستخدم bind عشان تدمج this مع ال context اللي احنا عاوزينه وترجعلنا function نستخدمها كل مره فاكره نفس الvalues
const person = {
firstName:"John",
lastName: "Doe",
fullName: function () {
return this.firstName + " " + this.lastName;
}
}
const osama = {
firstName:"Osama",
lastName: "Soliman",
}
let osamaFullName = person.fullName.bind(osama);
console.log(osamaFullName()); // Output: Osama Soliman
وبكدا نكون عملنا function كل مره فاكرة ال this بتاعة الnew Object
طيب ايه الفرق بين call و apply و bind ؟
Call
invokes the function and allows you to pass in arguments one by one.Apply
invokes the function and allows you to pass in arguments as an array.Bind
returns a new function, allowing you to pass in a this array and any number of arguments.
الدرس الثامن:
تعالو نتكلم حبة عن ال Arrow function
مثال:
const sayHi = () => {
console.log('hi');
console.log('this is:', this); // Output: `window object`
}
وهنا ميزه كويسة جداً في ال Arrow function ان هي مش بتحتفظ بقيمة this
وده مفيد جداً في حالات زي ال timers او ال callbacks مثلاً:
class Car{
produceCar(){
setInterval(function(){
console.log('new car produced');
console.log('this is: ', this)
},1000) //TODO: make it bit longer
}
}
const car = new Car();
car.produceCar(); // Output: this is: `window object`
هنلاقي هنا ان this عايدة على ال window object ومش عايدة على ال object من الكلاس طيب ايه الحل؟ ببساطه ممكن نستخدم call,bind,apply او نستخدم ال arrow functions
في دروسنا الجاية، هنستمر في استكشاف مواضيع أعمق في عالم JavaScript. فخليك متابع معانا، ولو عندك أي سؤال أو تعليق، ما تترددش في طرحه. شكرًا لمتابعتكم ولحد اللقاء في الدرس الجاي!