Kodokon kodokon.com

‏this والنماذج الأولية والأصناف

افهم كيف يُحلّ this ديناميكيا، وكيف تعمل سلسلة النماذج الأولية، وما الذي تضيفه الأصناف فعلا إلى نموذج الكائنات.

10 دقيقة · 3 أسئلة

افتح هذا الدرس في Kodokon

تُقرَّر قيمة this عند موضع الاستدعاء، لا وقت التصريح. أربع قواعد بترتيب أولوية متناقص: الاستدعاء بـ new، والارتباط الصريح (call وapply وbind)، والاستدعاء كتابع (obj.fn())، والاستدعاء البسيط (fn()) الذي يعطي undefined في النمط الصارم. وينبثق منها مباشرة أشيع خطأ في الواقع: استخراج تابع من كائنه يكسر الارتباط الضمني.

JAVASCRIPT
const user = {
  name: "Ada",
  greet() {
    return "Hello, " + this.name;
  },
};
console.log(user.greet()); // "Hello, Ada"
const detached = user.greet;
// detached(); // TypeError: this is undefined
const bound = user.greet.bind(user);
console.log(bound()); // "Hello, Ada"
يتلاشى الارتباط الضمني بمجرد استخراج التابع.

لا تملك الدوال السهمية this خاصا بها: بل تلتقطه معجميا من النطاق المحيط، تماما كالإغلاق. وهذا يجعلها مثالية للاستدعاءات المرتدة، لكنها معاكسة للمقصود كتوابع على كائنات حرفية، حيث سيشير this إلى النطاق الخارجي. وفي العمق، يفوّض كل كائن عبر سلسلة نماذجه الأولية: يُبحث عن الخاصية المفقودة حلقة إثر حلقة حتى الوصول إلى null.

JAVASCRIPT
function Animal(name) {
  this.name = name;
}
Animal.prototype.describe = function () {
  return this.name + " is an animal";
};
const dog = new Animal("Rex");
console.log(dog.describe()); // "Rex is an animal"
console.log(Object.getPrototypeOf(dog) ===
  Animal.prototype); // true
console.log(dog.hasOwnProperty("describe")); // false
يعيش describe على النموذج الأولي، مشتركا بين كل مثيل.

لا تغيّر بنية class هذا النموذج: بل تجعله مقروءا. تحطّ التوابع المصرَّح بها في جسم الصنف على Constructor.prototype فتكون بذلك مشتركة. أما حقول المثيل (بما فيها الدوال السهمية المسندة كحقول) فتُعاد إنشاؤها لكل مثيل: ارتباط this مضمون، لكن بكلفة ذاكرة مضاعفة. وأخيرا، توفر حقول #private خصوصية يفرضها المحرك، خلافا لاصطلاح _underscore.

JAVASCRIPT
class BankAccount {
  #balance = 0;
  deposit(amount) {
    if (amount <= 0) throw new Error("Invalid amount");
    this.#balance += amount;
    return this;
  }
  get balance() {
    return this.#balance;
  }
}
const account = new BankAccount();
account.deposit(50).deposit(25);
console.log(account.balance); // 75
حقل خاص يفرضه المحرك وواجهة قابلة للتسلسل.

اختبار المعرفة

تأكّد من أنك تذكّرت النقاط الأساسية في هذا الدرس.

  1. في النمط الصارم، ما قيمة this أثناء استدعاء بسيط fn() بلا كائن ولا ارتباط صريح؟
    • globalThis
    • undefined
    • الكائن الذي صُرّح فيه fn
    • null
  2. أين تُخزَّن التوابع المصرَّح بها في جسم صنف (باستثناء الحقول)؟
    • على كل مثيل، منسوخة وقت الإنشاء
    • على Constructor.prototype، مشتركة بين كل المثيلات
    • في نطاق داخلي غير قابل للوصول
  3. ما الخاصية المميزة للدالة السهمية فيما يتعلق بـ this؟
    • تربط this بالكائن المُستدعي، كأي تابع
    • لا تملك this خاصا بها وتلتقط الذي من النطاق المحيط
    • تربط this دائما بـ globalThis
    • تمنع أي وصول إلى this