ECMAScript-objektin muuttaminen

ECMAScriptin avulla voidaan luoda objekteja sekä muuttaa olemassa olevien objektien käyttäytymistä.

Prototype-ominaisuus voi määrittää rakentajan ominaisuudet ja metodit sekä lisätä paikallisiin objekteihin ominaisuuksia ja menetelmiä.

Luo uusi menetelmä

Luo uusia menetelmiä olemassa olevista menetelmistä

Voit käyttää prototype-ominaisuutta määrittääksesi uusia menetelmiä kaikille olemassa oleville luokille, aivan kuten omille luokille. Esimerkiksi, muistatko Number-luokan toString() -menetelmän? Jos sille annetaan parametri 16, se tulostaa heksadesimaalisen merkkijonon. Jos parametri on 2, se tulostaa binäärimerkkijonon. Voimme luoda menetelmän, joka voi muuntaa suoran numeron suoraan heksadesimaaliseksi merkkijonoksi. Tämä menetelmä on hyvin yksinkertainen:

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

Tässä ympäristössä avainsana this viittaa Number-oliota, joten voit täysin käyttää Number-olion kaikkia menetelmiä. Tämän koodin avulla voit toteuttaa seuraavat toiminnot:

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

TIY

Koska numero 15 on heksadesimaalisessa muodossa F, varoitus näyttää "F".

Nimeä olemassa olevat menetelmät ymmärrettävämmiksi

Voimme myös nimetä olemassa olevat menetelmät ymmärrettävämmiksi nimillä. Esimerkiksi, voimme lisätä Array-luokkaan kaksi metodia enqueue() ja dequeue(), jotka kutsumalla vain olemassa olevia push() ja shift() -menetelmiä:

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

TIY

Lisää uusia menetelmiä, jotka eivät liity mihinkään olemassa olevaan menetelmään

Totta kai, voit myös lisätä uusia menetelmiä, jotka eivät liity mihinkään olemassa olevaan menetelmään. Esimerkiksi, jos haluat arvioida jossain kohdassa taulukon sijaintia, ei ole olemassa paikallista menetelmää, joka voisi tehdä tämän. Voimme helposti luoda seuraavan menetelmän:

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

Tämä indexOf() -menetelmä on sama kuin String-luokan samanniminen menetelmä, ja se etsii jokaisesta elementistä taulukossa, kunnes löytää vastaavan elementin. Jos löytyy vastaava elementti, se palauttaa sen sijainnin, muuten -1.

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

TIY

Lisää uusia menetelmiä paikallisille objekteille

Lopuksi, jos haluat lisätä uuden metodin kaikille ECMAScript-objekteille, on määriteltävä se Object-objektin prototype-ominaisuudelle. Kuten aiemmissa luvuissa on kuvattu, kaikki paikalliset objektit perivät Object-objektista, joten kaikkiin Object-objektiin tehdyn muutoksen vaikutus näkyy kaikissa paikallisissa objekteissa. Esimerkiksi, jos haluat lisätä metodin, joka varoittaa objektin nykyisestä arvosta, voit käyttää seuraavaa koodia:

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

TIY

Tässä String- ja Number-objektit ovat saaneet showValue() metodin Object-objektista, ja niitä kutsutaan niiden objekteilla, mikä näyttää "hello" ja "25".

Olemassa olevien menetelmien määrittely uudelleen

Kuten voidaan määritellä uusia menetelmiä olemassa oleville luokille, voidaan myös määritellä olemassa olevia menetelmiä uudelleen. Kuten edellisissä luvuissa on kuvattu, funktioiden nimet ovat vain viittauksia funktioihin, joten ne voidaan helposti osoittaa muihin funktioihin. Jos muutetaan paikallista metodia, kuten toString(), mitä tapahtuu?

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

Aiemmin esitetty koodi on täysin laillista, ja sen suoritus on täysin odotettu:

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

TIY

Totta kai muistat, että Function-objektin luvussa on esitelty, että Function-objektin toString()-metodi yleensä tulostaa funtion alkuperäisen koodin. Metodin korvaaminen voi palauttaa toisen merkkijonon (tässä esimerkissä, "Function code hidden"). Mutta mitä tapahtuu toString()-metodia osoittavalle alkuperäiselle funktiolle? Se palautetaan käyttämättömien tallennusyksiköiden palautusohjelmalla, koska se on täysin hylätty. Ei ole tapaa palauttaa alkuperäistä funktiota, joten turvallisin tapa ennen alkuperäisen metodin korvaamista on tallentaa sen osoitin, jotta sitä voidaan käyttää myöhemmin. Joskus voi jopa kutsua alkuperäistä metodia uudessa metodissa:

Function.prototype.originalToString = Function.prototype.toString;
Function.prototype.toString = function() {
  if (this.originalToString().length > 100) {
    return "Funktio liian pitkä näyttää.";
  }
    return this.originalToString();
  }
};

TIY

Tässä koodissa ensimmäinen rivi tallentaa viittauksen nykyiseen toString() -menetelmään ominaisuuteen originalToString. Sitten mukautettu menetelmä korvaa toString() -menetelmän. Uusi menetelmä tarkistaa, onko funktiokoodin pituus yli 100. Jos on, se palauttaa virheilmoituksen, joka sanoo, että funktiokoodi on liian pitkä, muuten se kutsuu originalToString() -menetelmää ja palauttaa funktiokoodin alkuperäisen tekstin.

Myöhäinen sitoutuminen (Very Late Binding)

Teknisesti ei ole olemassa myöhäistä sitoutumista. Tämä kirja käyttää termiä kuvata ECMAScriptissä tapahtuvaa ilmiötä, jossa voidaan määrittää objektin metodit sen instanssoidaan jälkeen. Esimerkiksi:

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

TIY

Useimmissa ohjelmointikielissä on määritettävä objektin metodit ennen sen instanssointia. Tässä metodit sayHi() lisätään Object-luokan instanssin luomisen jälkeen. Perinteisissä kielissä ei ole koskaan kuultu tällaista toimintaa, eikä olekaan kuultu, että tämä metodi antaa automaattisesti Object-objektin instansseille käyttöönoton ja käyttöönoton välittömästi (seuraavassa rivissä).

Huomioitavaa:Ei suositella myöhäistä sitoutumista, koska sitä on vaikea jäljittää ja tallentaa. On kuitenkin hyvä tietää tämä mahdollisuus.