الدليل الكامل لهذا في 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()
طريقة.
طريقتان لإنجاحه:
- قبل إنشاء السياق الجديد ، قم بتعيين
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();
- باستخدام 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();