الدليل الكامل لهذا في JavaScript

في JavaScript ، تحتوي كل وظيفة على thisمرجع يتم إنشاؤه تلقائيًا عندما تعلن عنه.

جافا سكريبت thisتشبه إلى حد بعيد thisالمرجع في اللغات الأخرى القائمة على الفئة مثل Java أو C # (JavaScript هي لغة قائمة على النموذج الأولي وليس مفهوم "class"): يشير إلى الكائن الذي يستدعي الوظيفة (يسمى هذا الكائن أحيانًا كما السياق ). في جافا سكريبت، ولكن، في thisإشارة داخل ظائف يمكن أن تكون ملزمة لكائنات مختلفة تبعا للمكان الذي يتم استدعاء الدالة .

فيما يلي 5 قواعد أساسية thisللربط في JavaScript:

المادة 1

عندما يتم استدعاء دالة في النطاق العام ، يكون thisالمرجع مرتبطًا افتراضيًا بالكائن العام ( windowفي المستعرض أو globalفي Node.js). فمثلا:

function foo() { this.a = 2; } foo(); console.log(a); // 2

ملاحظة: إذا قمت بتعريف foo()الوظيفة أعلاه في الوضع المتشدد ، فإنك تستدعي هذه الوظيفة في النطاق العام ، thisوستكون undefinedالتعيين this.a = 2وسيطرح Uncaught TypeErrorالاستثناء.

القاعدة 2

دعنا نفحص المثال أدناه:

function foo() { this.a = 2; } const obj = { foo: foo }; obj.foo(); console.log(obj.a); // 2

من الواضح ، في المقتطف أعلاه ، أن foo()الوظيفة التي يتم استدعاؤها مع السياق هي objكائن thisوالمرجع الآن مرتبط به obj. لذلك عندما يتم استدعاء دالة مع كائن سياق ، فإن thisالمرجع سيكون مرتبطًا بهذا الكائن.

المادة 3

.call، .applyو .bindيمكن لجميع استخدامها في موقع الدعوة إلى صراحة مأزق this. الاستخدام .bind(this)شيء قد تراه في الكثير من مكونات React.

const foo = function() { console.log(this.bar) } foo.call({ bar: 1 }) // 1

إليك مثال سريع على كيفية استخدام كل واحد للربط this:

  • .call(): fn.call(thisObj, fnParam1, fnParam2)
  • .apply(): fn.apply(thisObj, [fnParam1, fnParam2])
  • .bind(): const newFn = fn.bind(thisObj, fnParam1, fnParam2)

القاعدة 4

function Point2D(x, y) { this.x = x; this.y = y; } const p1 = new Point2D(1, 2); console.log(p1.x); // 1 console.log(p1.y); // 2

الشيء الذي يجب أن تلاحظه هو Point2Dالوظيفة التي تسمى newبالكلمة الأساسية ، thisوالمرجع مرتبط p1بالكائن. لذلك عندما يتم استدعاء دالة باستخدام newالكلمة الأساسية ، فإنها ستنشئ كائنًا جديدًا thisوسيتم ربط المرجع بهذا الكائن.

ملاحظة: عندما تستدعي دالة newبالكلمة الأساسية ، فإننا نسميها أيضًا وظيفة مُنشئ .

القاعدة 5

تحدد JavaScript القيمة thisفي وقت التشغيل ، بناءً على السياق الحالي. لذلك thisيمكن أن يشير أحيانًا إلى شيء آخر غير ما تتوقعه.

ضع في اعتبارك هذا المثال لفئة Cat باستخدام طريقة تسمى makeSound()، باتباع النمط الوارد في القاعدة 4 (أعلاه) مع وظيفة المُنشئ newوالكلمة الأساسية.

const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.makeSound(); // Fat Daddy says: Mrrooowww

الآن دعونا نحاول إعطاء القطة وسيلة annoy()للناس من خلال تكرار صوته 100 مرة ، مرة كل نصف ثانية.

const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const t = setInterval(function() { this.makeSound(); // <-- this line fails with `this.makeSound is not a function` count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();

هذا لا يعمل لأننا داخل setIntervalرد الاتصال أنشأنا سياقًا جديدًا بنطاق عالمي ، لذلك thisلم يعد يشير إلى مثيلنا كيتي. في متصفح الويب ، thisسيشير بدلاً من ذلك إلى كائن Window ، الذي لا يحتوي على makeSound()طريقة.

طريقتان لإنجاحه:

  1. قبل إنشاء السياق الجديد ، قم بتعيين thisمتغير محلي يسمى me، أو self، أو أيًا كان ما تريد تسميته ، واستخدم هذا المتغير داخل رد الاتصال.
const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const self = this; const t = setInterval(function() { self.makeSound(); count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();
  1. باستخدام ES6 ، يمكنك تجنب التخصيص thisلمتغير محلي باستخدام وظيفة السهم ، والتي ترتبط thisبسياق الكود المحيط حيث يتم تعريفه.
const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const t = setInterval(() => { this.makeSound(); count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();