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

تشير الكلمة الرئيسية 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