What is this in JavaScript بالعربي

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؟

ونفتكر التويته دي مع بعض 😂


الدرس الأول:

💡
When you call function on nothing... You call it on the 'global object'

يعني ايه؟

يعني لو عملت Function اسمها greet في الكود بتاعك انت في الأصل بتعملها في ال global object

function greet(){
    console.log('hi');
}

يعني اكنك بالظبط كاتب

window.greet = function(){
    console.log('hi');
}

الدرس الثاني:

نستنتج من هنا قاعدة مهمة جداً للتعامل مع this

💡
The "Left of The Dot" Rule.
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 بتاعتنا

💡
The "Left of The Dot" 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. فخليك متابع معانا، ولو عندك أي سؤال أو تعليق، ما تترددش في طرحه. شكرًا لمتابعتكم ولحد اللقاء في الدرس الجاي!

متنساش تدوس ❤️ لو عجبتك سلسلة الدروس