تعمل هذه الكلمة الرئيسية

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

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

الربط العالمي

خارج دالة أو سياق كائن، تشير السمة this إلى السمة globalThis، وهي مرجع إلى الكائن العمومي في معظم بيئات JavaScript. في سياق نص برمجي يتم تشغيله في متصفح ويب، يكون الكائن العمومي هو window:

this;
> Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, ...}

في Node.js، يكون globalThis هو كائن global:

$ node
Welcome to Node.js v20.10.0.
Type ".help" for more information.
> this
<ref *1> Object [global] {
...
}

خارج الوضع المتشدد، تشير this أيضًا إلى الكائن العمومي داخل دالة مستقلة، لأن العنصر الرئيسي Window هو الكائن الذي "يمتلك" تلك الدوال بشكل فعّال.

function myFunction() {
    console.log( this );
}
myFunction();
> Window {...}

(function() {
    console.log( this );
}());
> Window {...}

عند استخدام الوضع المتشدد، تكون قيمة this هي undefined داخل دالة مستقلة:

(function() {
    "use strict";
    console.log( this );
}());
> undefined

قبل طرح الوضع المتشدد، سيتم استبدال القيمة null أو undefined الخاصة بـ this بإشارة إلى الكائن العمومي. قد ترى أحيانًا أنّ عملية الربط العالمي يُشار إليها باسم "الربط التلقائي" بسبب هذا السلوك القديم.

الربط الضمني

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

let myObject = {
    myValue: "This is my string.",
    myMethod() {
            console.log( this.myValue );
    }
};

myObject.myMethod();
> "This is my string."

قد يبدو أنّ قيمة this تعتمد على كيفية تعريف الدالة وكائن تضمينها. بدلاً من ذلك، يكون سياق قيمة this هو سياق التنفيذ الحالي. في هذه الحالة، سياق التنفيذ هو أنّ الكائن myObject يستدعي طريقة myMethod، وبالتالي أنّ myObject هي قيمة this. قد يبدو لك أنّ هذه السمة تقنية في سياق الأمثلة السابقة، ولكن بالنسبة إلى الاستخدامات الأكثر تقدّمًا للسمة this، إنّها نقطة فارقة أساسية يجب أخذها في الاعتبار.

بشكل عام، يمكنك استخدام this بطرق لا تتوقع أن يكون الرمز البرمجي المحيط بها أي بنية معيّنة. ويُستثنى من هذه القاعدة دوال الأسهم في ES5.

this في الدوال السهمية

في دوال الأسهم، تتحوّل السمة this إلى ارتباط في بيئة تضمين أسلوب تضمين. وهذا يعني أنّ this في الدالة السهمية يشير إلى قيمة this في أقرب سياق تضمين لهذه الدالة:

let myObject = {
    myMethod() { console.log( this ); },
    myArrowFunction: () => console.log( this ),
    myEnclosingMethod: function () {
        this.myArrowFunction = () => { console.log(this) };
    }
};

myObject.myMethod();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }

myObject.myArrowFunction();
> Window {...}

في المثال السابق، يسجّل myObject.myMethod() myObject باعتباره الكائن الذي "يملك" هذه الطريقة، ولكن myObject.myArrowFunction() تعرض globalThis (أو undefined)، لأن مثيل this داخل دالة السهم يشير بدلاً من ذلك إلى أعلى نطاق تضمين.

في المثال التالي، تنشئ myEnclosingMethod دالة سهم على الكائن الذي يحتوي عليها عند تنفيذها. يشير مثيل this داخل دالة السهم الآن إلى قيمة this في بيئة التغليف، وهي الطريقة التي تحتوي على دالة السهم هذه. بما أنّ قيمة this داخل myEnclosingMethod تشير إلى myObject، بعد تعريف دالة السهم، يشير this داخل دالة السهم أيضًا إلى myObject:

let myObject = {
    myMethod() { console.log( this ); },
    myEnclosingMethod: function () {
        this.myArrowFunction = () => { console.log(this) };
    }
};

myObject.myEnclosingMethod();
myObject.myArrowFunction();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }

ربط صريح

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

var myObject = {
  myString: "This is my string.",
  myMethod() {
    console.log( this.myString );
  }
};
myObject.myMethod();
> "This is my string."

setTimeout( myObject.myMethod, 100 );
> undefined

على الرغم من أنّه تم حلّ هذا القصور المحدّد في setTimeout من خلال ميزات أخرى، تم سابقًا حلّ المشاكل المشابهة المتعلقة بـ "فقدان" السمة this، وذلك من خلال إنشاء إشارة واضحة إلى قيمة السمة this ضمن نطاق السياق المقصود. قد تظهر لك أحيانًا أمثلة this يتم تعيينها إلى متغيّر باستخدام معرّفات مثل that أو self أو _this في قواعد الرموز القديمة. هذه هي اصطلاحات المعرّفات الشائعة للمتغيّرات التي تحتوي على قيمة this تم تجاوزها.

عند استدعاء دالة باستخدام الطرق call() أو bind() أو apply()، يشير this بشكل صريح إلى الكائن الذي يتم استدعاؤه:

let myFunction = function() {
    console.log( this.myValue );
}

let myObject = {
   "myValue" : "This is my string."
 };

myFunction.call( myObject );
> "This is my string."
var myObject = {
  myString: "This is my string.",
  myMethod() {
    console.log( this.myString );
  }
};

setTimeout( myObject.myMethod.bind( myObject ), 100 );
> "This is my string."

تلغي الربط الصريح قيمة this التي توفرها الربط الضمني.

let myObject = {
    "myValue" : "This string sits alongside myMethod.",
    myMethod() {
        console.log( this.myValue );
    }
};
let myOtherObject = {
    "myValue" : "This is a string in another object entirely.",
};

myObject.myMethod.call( myOtherObject );
> "This is a string in another object entirely."

إذا تم استدعاء دالة بطريقة تضبط قيمة this على undefined أو null، يتم استبدال هذه القيمة بـ globalThis خارج الوضع المتشدد:

let myFunction = function() {
    console.log( this );
}

myFunction.call( null );
> Window {...}

وبالمثل، إذا تم استدعاء دالة بطريقة قد تعطي this قيمة أولية، يتم استبدال هذه القيمة بكائن برنامج تضمين القيمة الأولية خارج الوضع المتشدد:

let myFunction = function() {
    console.log( this );
}

let myNumber = 10;

myFunction.call( myNumber );
> Number { 10 }

في الوضع المتشدد، لا يتم فرض ظهور قيمة this التي تم تمريرها على كائن بأي شكل من الأشكال، حتى ولو كانت قيمة أساسية أو قيمة null أو undefined:

"use strict";
let myFunction = function() {
    console.log( this );
}

let myNumber = 10;

myFunction.call( myNumber );
> 10

myFunction.call( null );
> null

ربط new

عند استخدام class كدالة إنشائية باستخدام الكلمة الرئيسية new، تشير this إلى المثيل الذي تم إنشاؤه حديثًا:

class MyClass {
    myString;
    constructor() {
        this.myString = "My string.";
    }
    logThis() {
        console.log( this );
    }
}
const thisClass = new MyClass();

thisClass.logThis();
> Object { myString: "My string." }

وبالمثل، تشير قيمة this داخل دالة إنشائية تسمى استخدام new إلى الكائن الذي يتم إنشاؤه:

function MyFunction() {
  this.myString = "My string.";
  this.logThis = function() {
    console.log( this );
  }
}
const myObject = new MyFunction();

myObject.logThis();
> Object { myString: "My string.", logThis: logThis() }

ربط معالج الأحداث

في سياق معالِجات الأحداث، تشير قيمة this إلى العنصر الذي يستدعيها. داخل دالة معاودة الاتصال في معالج الأحداث، يعني هذا أن this يشير إلى العنصر المرتبط بالمعالج:

let button = document.querySelector( "button" );

button.addEventListener( "click", function( event ) { console.log( this ); } );

عندما يتفاعل مستخدم مع button في المقتطف السابق، تكون النتيجة هي كائن العنصر الذي يحتوي على <button> نفسه:

> Button {}

عند استخدام دالة سهم كاستدعاء أداة معالجة الحدث، يتم توفير قيمة this مرة أخرى من خلال أقرب سياق تنفيذ تضمين. وهذا يعني في أعلى مستوى أنّ this داخل دالة معاودة الاتصال في معالج الأحداث هو globalThis (أو undefined في الوضع المتشدد):

let button = document.querySelector( "button" );

button.addEventListener( "click", ( event ) => { console.log( this ); } );
> undefined

كما هو الحال مع أي كائن آخر، عند استخدام الطرق call() أو bind() أو apply() للإشارة إلى وظيفة معاودة الاتصال لأداة معالجة الحدث، تشير this إلى الكائن صراحةً:

let button = document.querySelector( "button" );
let myObject = {
    "myValue" : true
};
function handleClick() {
    console.log( this );
}

button.addEventListener( "click", handleClick.bind( myObject ) );
> Object { myValue: true }

التحقق من فهمك

بالنسبة إلى نص برمجي يتم تشغيله في متصفح ويب، ما هو الكائن العام الذي يشير إليه this عند استخدامه خارج دالة أو سياق كائن؟

الكائن window
الكائن browser
الكائن undefined