046_修改对象
1. prototype屬性不僅可以定義構造函數的屬性和方法, 還可以為本地對象添加屬性和方法。
2. 通過已有的方法創建新方法
2.1. 可以用prototype屬性為任何已有的類定義新方法, 就像處理自己的類一樣。例如, 還記得Number類的toString()方法嗎?如果給它傳遞參數16, 它將輸出十六進制的字符串。如果這個方法的參數是 2, 那么它將輸出二進制的字符串。我們可以創建一個方法, 可以把數字對象直接轉換為十六進制字符串。創建這個方法非常簡單:
Number.prototype.toHexString = function() {return this.toString(16); };2.2. 在此環境中, 關鍵字this指向Number的實例, 因此可完全訪問Number的所有方法。有了這段代碼, 可實現下面的操作:
var num = 15; alert(num.toHexString()); // 輸出"F"3. 重命名已有方法
3.1. 我們還可以為已有的方法命名更易懂的名稱。例如, 可以給Array類添加兩個方法enqueue()和dequeue(), 只讓它們反復調用已有的push()和shift()方法即可:
Array.prototype.enqueue = function(item) {this.push(item); };Array.prototype.dequeue = function() {return this.shift(); };4. 添加與已有方法無關的方法
4.1. 當然, 還可以添加與已有方法無關的方法。例如, 假設要判斷某個項在數組中的位置, 沒有本地方法可以做這種事情。我們可以輕松地創建下面的方法:
Array.prototype.indexOf = function (item) {for (let i=0; i<this.length; i++) {if (item== this[i]) {return i;}}return -1; }4.2. 該方法indexOf()與String類的同名方法保持一致, 在數組中檢索每個項, 直到發現與傳進來的項相同的項目為止。如果找到相同的項, 則返回該項的位置, 否則, 返回-1。有了這種定義, 我們可以編寫下面的代碼:
var colors = new Array("red", "green", "blue"); alert(colors.indexOf("green")); // 輸出"1"5. 為本地對象添加新方法
5.1. 最后, 如果想給JavaScript中每個本地對象添加新方法, 必須在Object對象的prototype屬性上定義它。所有本地對象都繼承了Object對象, 所以對Object 對象做任何改變, 都會反應在所有本地對象上。例如, 如果想添加一個用警告輸出對象的當前值的方法, 可以采用下面的代碼:
Object.prototype.showValue = function () {alert(this.valueOf()); };var str = "hello"; var num = 25; str.showValue(); // 輸出"hello" num.showValue(); // 輸出"25"5.2. 這里, String和Number對象都從Object對象繼承了showValue()方法, 分別在它們的對象上調用該方法, 將顯示"hello"和"25"。
6. 重定義已有方法
6.1. 就像能給已有的類定義新方法一樣, 也可重定義已有的方法。函數名只是指向函數的指針, 因此可以輕松地指向其他函數。如果修改了本地方法, 如toString(), 會出現什么情況呢?
Function.prototype.toString = function() {return "Function code hidden"; } 6.2. 前面的代碼完全合法, 運行結果完全符合預期: function sayHi() {alert("hi"); }alert(sayHi.toString()); // 輸出"Function code hidden"6.3. Function對象的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();} };6.4. 在這段代碼中, 第一行代碼把對當前toString()方法的引用保存在屬性originalToString中。然后用定制的方法覆蓋了toString()方法。新方法將檢查該函數源代碼的長度是否大于 100。如果是, 就返回錯誤信息, 說明該函數代碼太長, 否則調用 originalToString()方法, 返回函數的源代碼。
總結
- 上一篇: 045_对象作用域
- 下一篇: 044_定义类或对象