تعديل الأحداث ECMAScript

من خلال استخدام ECMAScript، يمكن إنشاء عناصر ويمكن أيضًا تعديل سلوك العناصر الموجودة.

خصائص البروتوتيب يمكن أن تحدد خصائص وطرق بناء الصيغة، ويمكن أيضًا إضافة خصائص وطرق إلى العنصر المحلي.

إنشاء طرق جديدة

إنشاء طرق جديدة باستخدام الطرق الموجودة

يمكنك استخدام خاصية prototype لتحديد طرق جديدة لأي فئة موجودة، مثل معالجة فئة الخاصة بك. على سبيل المثال، هل تتذكر طريقة toString() الخاصة بفئة Number؟ إذا تم إرسالها مع 参数 16، فإنها ستقوم بطباعة النص البيناري. إذا تم إرسالها مع 参数 2، فإنها ستقوم بطباعة النص الثنائي. يمكنك إنشاء طريقة يمكنها تحويل مثال عدد مباشرة إلى نص ثنائي. إن إنشاء هذه الطريقة بسيط للغاية:

Number.prototype.toHexString = function() {
  return this.toString(16);
};

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

var iNum = 15;
alert(iNum.toHexString());		//الخروج "F"

TIY

بما أن الرقم 15 يساوي F في النظام العشري، فإن التحذير سيظهر "F".

تغيير أسماء الطرق الموجودة

يمكنك أيضًا تغيير أسماء الطرق الموجودة لجعلها أكثر وضوحًا. على سبيل المثال، يمكنك إضافة طريقتين جديدتين إلى فئة Array هما enqueue() و dequeue()، وتجعلها تُدعو طريقتي push() و shift() بشكل متكرر فقط:

Array.prototype.enqueue = function(vItem) {
  this.push(vItem);
};
Array.prototype.dequeue = function() {
  return this.shift();
};

TIY

إضافة طرق جديدة غير مرتبطة بالمطالبات الموجودة

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

Array.prototype.indexOf = function (vItem) {
  for (var i=0; i<this.length; i++) {
    if (vItem == this[i]) {
	  return i;
	}
  }
  return -1;
}

هذه الطريقة indexOf() تتمتع بنفس التعريف مع الطريقة المماثلة في فئة String، حيث تقوم بالبحث في كل عنصر من العناصر في البنية، حتى يجد العنصر المتطابق مع العنصر المرسل إليها. إذا تم العثور على العنصر المتطابق، يتم العودة إلى موقع العنصر، وإلا يتم العودة إلى -1. بهذا التعريف، يمكننا كتابة الكود التالي:

var aColors = new Array("red","green","blue");
alert(aColors.indexOf("green"));	//يخرج "1"

TIY

إضافة طرق جديدة إلى الكائن المحلي

في النهاية، إذا كنت ترغب في إضافة طريقة جديدة إلى كل كائن محلي في ECMAScript، يجب تعريفها على الخاصية prototype لكلاسي Object. كما ذكرنا في الفصول السابقة، تنقل جميع الكائنات المحلية كلاسي Object، لذا ستؤثر أي تغيير على كلاسي Object على جميع الكائنات المحلية. على سبيل المثال، إذا كنت ترغب في إضافة طريقة لإخراج القيمة الحالية للكائن بالتحذير، يمكنك استخدام الكود التالي:

Object.prototype.showValue = function () {
  alert(this.valueOf());
};
var str = "hello";
var iNum = 25;
str.showValue();		//يخرج "hello"
iNum.showValue();		//يخرج "25"

TIY

في هذا المكان، استقبلت كلاسي Object و Number من كلاسي Object طريقة showValue()، تم استدعاء هذه الطريقة على كل من الكائنات، سيتم عرض "hello" و "25".

تعريف طرق جديدة

مثلما يمكنك إضافة طرق جديدة إلى كلاسات مسبقة التعريف، يمكنك أيضًا تعريف طرق جديدة. كما ذكرنا في الفصول السابقة، اسم الوظيفة هو مجرد مؤشر إلى الوظيفة، لذا يمكن بسهولة أن يشير إلى وظيفة أخرى. ماذا سيحدث إذا تم تعديل الطريقة المحلية، مثل toString()؟

Function.prototype.toString = function() {
  return "Function code hidden";
}

النص البرمجي السابق صحيح تمامًا، والنتيجة مطابقة للتحليل المتوقع:

function sayHi() {
  alert("hi");
}
alert(sayHi.toString());	//يخرج "Function code hidden"

TIY

ربما تذكر أن Method Function هذا الفصل تم تقديم Method toString() للعادة ما تكون النتيجة خروج ميزة هي رمز ميزة (في هذا المثال، يمكن أن يكون "Function code hidden"). ومع ذلك، ماذا يحدث للوظيفة الأصلية التي يشير إليها toString()؟ سيتم استعادتها من وحدة التخزين العاطلة عن العمل، لأنها تم التخلص منها تمامًا. لا يوجد طريقة لإستعادة الوظيفة الأصلية، لذا فإن الحركة الأكثر أمانًا قبل تغيير الطريقة الأصلية هي تخزين مؤشرها من أجل الاستخدام في المستقبل. في بعض الأحيان قد تكون بحاجة إلى استدعاء الطريقة الأصلية في الطريقة الجديدة:

Function.prototype.originalToString = Function.prototype.toString;
Function.prototype.toString = function() {
  if (this.originalToString().length > 100) {
    return "Function too long to display.";
  } else {
    return this.originalToString();
  }
};

TIY

في هذا الكود، يقوم السطر الأول بحفظ إشارة إلى الطريقة toString() الحالية في سمة originalToString. ثم يتم تغيير الطريقة toString() باستخدام طريقة مخصصة. ستتحقق الطريقة الجديدة من طول كود الوظيفة. إذا كان أطول من 100، فإنها ستعود إلى رسالة خطأ تشير إلى أن كود الوظيفة طويل جدًا، وإلا ستعود إلى طريقة originalToString() وتعيد كود الوظيفة المصدر.

التقييد المتأخر الشديد (Very Late Binding)

تقنيًا، لا وجود لـ Late Binding. يُستخدم هذا المصطلح في هذا الكتاب لوصف ظاهرة في ECMAScript، وهي القدرة على تعريف طرق الأجسام بعد تحديدية الأجسام. على سبيل المثال:

var o = new Object();
Object.prototype.sayHi = function () {
  alert("hi");
};
o.sayHi();

TIY

في معظم لغات البرمجة، يجب تعريف طرق الأجسام قبل تحديدية الأجسام. هنا، يتم إضافة الطريقة sayHi() بعد إنشاء نموذج Object. لم يسمع أحد من قبل عن هذا التكامل، ولا عن كيفية منح هذا النموذج للأجسام الخاصة به تلقائيًا ويمكن استخدامه على الفور (في السطر التالي).

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