Mengubah Objek ECMAScript

Dengan menggunakan ECMAScript, bukan hanya dapat mencipta objek, tetapi juga dapat mengubah tingkah laku objek yang sudah ada.

Properti prototype boleh untuk menyatakan atribut dan method konstruktur, serta menambah atribut dan method bagi objek lokal.

Membuat metod baru

Membuat metod baru melalui metod yang sudah ada

Kami dapat menggunakan atribut prototype untuk mendefinisikan metod baru untuk kelas yang sudah ada, seperti mengelola kelas sendiri. Contohnya, ingat metod toString() kelas Number? Jika dia menerima parameter 16, dia akan mengeluarkan string heksadesimal. Jika parameter metod ini adalah 2, dia akan mengeluarkan string biner. Kita dapat membuat metod yang dapat mengubah objek angka langsung ke string heksadesimal. Membuat metod ini sangat mudah:

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

Dalam lingkungan ini, kata kunci this menunjuk ke instans Number, sehingga dapat mengakses semua metod Number. Dengan kode ini, operasi di bawah ini dapat dilakukan:

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

TIY

Karena angka 15 sama dengan F di heksadesimal, peringatan akan menampilkan "F".

Mengubah nama metod yang sudah ada

Kami juga dapat menamakan metod yang sudah ada menjadi nama yang lebih mudah untuk memahami. Contohnya, kita dapat menambahkan dua metod enqueue() dan dequeue() ke kelas Array, hanya memanggil metod push() dan shift() yang sudah ada:

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

TIY

Tambahkan metod yang berbeda dengan metod yang sudah ada

Tentu, kita dapat menambahkan metod yang berbeda dengan metod yang sudah ada. Contohnya, asumsikan bahwa kita ingin mengecek posisi item di dalam array tanpa metod yang sudah ada untuk melakukan hal ini. Kita dapat dengan mudah membuat metod di bawah ini:

Array.prototype.indexOf = function (vItem) {
  untuk (var i=0; i<this.length; i++) {
    jika (vItem == this[i]) {
	  kembalikan i;
	}
  }
  kembalikan -1;
}

Keputusan indexOf() ini disesuaikan dengan metod yang sama di kelas String, mencari setiap item di dalam array hingga mendapati item yang sama yang disampaikan. Jika item yang sama ditemukan, posisi item itu akan kembalikan, jika tidak, kembalikan -1. Dengan definisi ini, kita dapat menulis kode di bawah ini:

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

TIY

Menambahkan metode baru ke objek lokal

Akhirnya, jika ingin menambahkan metode baru ke setiap objek lokal dalam ECMAScript, harus mendefinisikan di properti prototype objek Object. Seperti yang disebutkan di bab sebelumnya, semua objek lokal mewarisi objek Object, jadi setiap perubahan yang dilakukan terhadap objek Object akan berpengaruh kepada semua objek lokal. Contohnya, jika ingin menambahkan metode untuk menampilkan nilai saat ini objek dengan peringatan, dapat menggunakan kode berikut:

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

TIY

Di sini, objek String dan Number mewarisi metode showValue() dari objek Object, memanggil metodenya di atas objek masing-masing, akan menampilkan "hello" dan "25".

Mendefinisikan ulang metode yang sudah ada

Sama seperti dapat memberikan definisi metode baru untuk kelas yang sudah ada, dapat juga mendefinisikan ulang metode yang sudah ada. Seperti yang disebutkan di bab sebelumnya, nama fungsi hanya mengacu ke alamat fungsi, jadi dapat dengan mudah menunjuk ke fungsi lain. Jika mengubah metode lokal, seperti toString(), apa yang akan terjadi?

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

Kode sebelumnya sepenuhnya sah, hasil eksekusi sepenuhnya sesuai dengan harapan:

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

TIY

Anda mungkin ingat, dalam bab Function object ini, dijelaskan bahwa metode toString() biasanya mengeluarkan kode sumber fungsi. Menimpa metode ini, dapat mengembalikan string lain (di contoh ini, dapat mengembalikan "Function code hidden"). Namun, apa yang terjadi dengan fungsi asli yang ditunjuk toString()? Dia akan disimpan dalam area penyimpanan yang tak digunakan oleh program pengembalian memori, karena telah disingkirkan sepenuhnya. Tidak ada cara untuk memulihkan fungsi asli, jadi cara yang paling aman sebelum menimpa metode asli adalah menyimpan alamatnya untuk penggunaan nantinya. Kadang-kadang Anda bahkan dapat memanggil metode asli di dalam metode baru:

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 对象的实例并能立即使用(接下来的一行)。

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