Modifying Objects in ECMAScript

通过使用 ECMAScript,不仅可以创建对象,还可以修改已有对象的行为。

prototype 属性不仅可以定义构造函数的属性和方法,还可以为本地对象添加属性和方法。

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

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

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

Number.prototype.toHexString = function() {
  تعود 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() {
  تعود this.shift();
};

TIY

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

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

Array.prototype.indexOf = function (vItem) {
  للأسفل (var i=0; i<this.length; i++) {
    إذا (vItem == this[i]) {
	  تعود i;
	}
  }
  تعود -1;
}

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

var aColors = new Array("red","green","blue");
alert(aColors.indexOf("green"));	//Output "1"

TIY

Kawo methodi na farko ga obyekti na farko

Kafin kuma, domin za a iya kawo methodi na farko ga kowane obyekti na ECMAScript, za a iya kawo ita a cikin prototype属性 na Object obyekti. Duk da cewa a baya ya nuna, duk obyekti na farko sun kammala Object obyekti, domin za a iya kawo amfani da kowane wuri a Object obyekti, za a iya kawo amfani da ita a kowane obyekti. Misali, domin za a iya kawo methodi na farko da za a iya yin amfani da ita, za a iya yin amfani da ita:

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

TIY

Har ila yau, String da Number obyekti sun kammala showValue() methodi daga Object obyekti, ana yin amfani da ita a cikin obyekti, ana nuna "hello" da "25".

Kawo methodi na farko

Kamar yadda za a iya kawo methodi na farko ga nau'in fannin da ake amfani da, za a iya kawo methodi na farko. Duk da cewa, kamar yadda ita ce bayanin baya, za a iya kawo shi ga fannin. domin za a iya kawo amfani da ita, ana ba da shi shi a lokacin yin kayan aikin. Kamar yadda a baya ya nuna, lambar fannin ita ce fannin da ke nuna fannin, domin za a iya kawo ita ga fannin na farko. domin za a iya kawo amfani da methodi na farko, kamar toString(), za a iya samun kuma?

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

Koda na farko ya kai a hankali, sakamakon su ya kai a hankali:

function sayHi() {
  alert("hi");
}
alert(sayHi.toString());	//Output "Function code hidden"

TIY

Kai ka na iya ka sanata, Function obyekti ita abinci kafin ita ya na sayHi() methodi kowa ya hanyar kodo na fannin. A kai wa kafin, za a iya yin string maki (a bikiya, za a iya yin "Function code hidden"). Babban methodi, za a hanyar kafin, za a iya yin gurɗi maki, domin ya ya yi a fassara. Man ne ba za a iya kawo wa gurɗi methodi na farko, domin za a iya yin karewa, domin za a iya yin amfani da ita kafin. Koyaushe, za a iya yin amfani da methodi na farko a cikin methodi na farko:

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)

从技术上讲,根本不存在极晚绑定。本书采用该术语描述 ECMAScript 中的一种现象,即能够在对象实例化后再定义它的方法。例如:

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

TIY

在大多数程序设计语言中,必须在实例化对象之前定义对象的方法。这里,方法 sayHi() 是在创建 Object 类的一个实例之后来添加进来的。在传统语言中不仅没听说过这种操作,也没听说过该方法还会自动赋予 Object 对象的实例并能立即使用(接下来的一行)。

注意:不建议使用极晚绑定方法,因为很难对其跟踪和记录。不过,还是应该了解这种可能。