ECMAScript 修改對(duì)象

2018-09-21 17:51 更新

通過(guò)使用 ECMAScript,不僅可以創(chuàng)建對(duì)象,還可以修改已有對(duì)象的行為。

prototype 屬性不僅可以定義構(gòu)造函數(shù)的屬性和方法,還可以為本地對(duì)象添加屬性和方法。

創(chuàng)建新方法

通過(guò)已有的方法創(chuàng)建新方法

可以用 prototype 屬性為任何已有的類(lèi)定義新方法,就像處理自己的類(lèi)一樣。例如,還記得 Number 類(lèi)的 toString() 方法嗎?如果給它傳遞參數(shù) 16,它將輸出十六進(jìn)制的字符串。如果這個(gè)方法的參數(shù)是 2,那么它將輸出二進(jìn)制的字符串。我們可以創(chuàng)建一個(gè)方法,可以把數(shù)字對(duì)象直接轉(zhuǎn)換為十六進(jìn)制字符串。創(chuàng)建這個(gè)方法非常簡(jiǎn)單:

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

在此環(huán)境中,關(guān)鍵字 this 指向 Number 的實(shí)例,因此可完全訪問(wèn) Number 的所有方法。有了這段代碼,可實(shí)現(xiàn)下面的操作:

var iNum = 15;
alert(iNum.toHexString());		//輸出 "F"

TIY

由于數(shù)字 15 等于十六進(jìn)制中的 F,因此警告將顯示 "F"。

重命名已有方法

我們還可以為已有的方法命名更易懂的名稱(chēng)。例如,可以給 Array 類(lèi)添加兩個(gè)方法 enqueue() 和 dequeue(),只讓它們反復(fù)調(diào)用已有的 push() 和 shift() 方法即可:

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

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

TIY

添加與已有方法無(wú)關(guān)的方法

當(dāng)然,還可以添加與已有方法無(wú)關(guān)的方法。例如,假設(shè)要判斷某個(gè)項(xiàng)在數(shù)組中的位置,沒(méi)有本地方法可以做這種事情。我們可以輕松地創(chuàng)建下面的方法:

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

  return -1;
}

該方法 indexOf() 與 String 類(lèi)的同名方法保持一致,在數(shù)組中檢索每個(gè)項(xiàng),直到發(fā)現(xiàn)與傳進(jìn)來(lái)的項(xiàng)相同的項(xiàng)目為止。如果找到相同的項(xiàng),則返回該項(xiàng)的位置,否則,返回 -1。有了這種定義,我們可以編寫(xiě)下面的代碼:

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

TIY

為本地對(duì)象添加新方法

最后,如果想給 ECMAScript 中每個(gè)本地對(duì)象添加新方法,必須在 Object 對(duì)象的 prototype 屬性上定義它。前面的章節(jié)我們講過(guò),所有本地對(duì)象都繼承了 Object 對(duì)象,所以對(duì) Object 對(duì)象做任何改變,都會(huì)反應(yīng)在所有本地對(duì)象上。例如,如果想添加一個(gè)用警告輸出對(duì)象的當(dāng)前值的方法,可以采用下面的代碼:

Object.prototype.showValue = function () {
  alert(this.valueOf());
};

var str = "hello";
var iNum = 25;
str.showValue();		//輸出 "hello"
iNum.showValue();		//輸出 "25"

TIY

這里,String 和 Number 對(duì)象都從 Object 對(duì)象繼承了 showValue() 方法,分別在它們的對(duì)象上調(diào)用該方法,將顯示 "hello" 和 "25"。

重定義已有方法

就像能給已有的類(lèi)定義新方法一樣,也可重定義已有的方法。如前面的章節(jié)所述,函數(shù)名只是指向函數(shù)的指針,因此可以輕松地指向其他函數(shù)。如果修改了本地方法,如 toString(),會(huì)出現(xiàn)什么情況呢?

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

前面的代碼完全合法,運(yùn)行結(jié)果完全符合預(yù)期:

function sayHi() {
  alert("hi");
}

alert(sayHi.toString());	//輸出 "Function code hidden"

TIY

也許你還記得,F(xiàn)unction 對(duì)象這一章中介紹過(guò) Function 的 toString() 方法通常輸出的是函數(shù)的源代碼。覆蓋該方法,可以返回另一個(gè)字符串(在這個(gè)例子中,可以返回 "Function code hidden")。不過(guò),toString() 指向的原始函數(shù)怎么了呢?它將被無(wú)用存儲(chǔ)單元回收程序回收,因?yàn)樗煌耆珡U棄了。沒(méi)有能夠恢復(fù)原始函數(shù)的方法,所以在覆蓋原始方法前,比較安全的做法是存儲(chǔ)它的指針,以便以后的使用。有時(shí)你甚至可能在新方法中調(diào)用原始方法:

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

在這段代碼中,第一行代碼把對(duì)當(dāng)前 toString() 方法的引用保存在屬性 originalToString 中。然后用定制的方法覆蓋了 toString() 方法。新方法將檢查該函數(shù)源代碼的長(zhǎng)度是否大于 100。如果是,就返回錯(cuò)誤信息,說(shuō)明該函數(shù)代碼太長(zhǎng),否則調(diào)用 originalToString() 方法,返回函數(shù)的源代碼。

極晚綁定(Very Late Binding)

從技術(shù)上講,根本不存在極晚綁定。本書(shū)采用該術(shù)語(yǔ)描述 ECMAScript 中的一種現(xiàn)象,即能夠在對(duì)象實(shí)例化后再定義它的方法。例如:

var o = new Object();

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

o.sayHi();

TIY

在大多數(shù)程序設(shè)計(jì)語(yǔ)言中,必須在實(shí)例化對(duì)象之前定義對(duì)象的方法。這里,方法 sayHi() 是在創(chuàng)建 Object 類(lèi)的一個(gè)實(shí)例之后來(lái)添加進(jìn)來(lái)的。在傳統(tǒng)語(yǔ)言中不僅沒(méi)聽(tīng)說(shuō)過(guò)這種操作,也沒(méi)聽(tīng)說(shuō)過(guò)該方法還會(huì)自動(dòng)賦予 Object 對(duì)象的實(shí)例并能立即使用(接下來(lái)的一行)。

注意:不建議使用極晚綁定方法,因?yàn)楹茈y對(duì)其跟蹤和記錄。不過(guò),還是應(yīng)該了解這種可能。

以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)