ECMAScript Ændre Objekt

Ved brug af ECMAScript kan man ikke kun oprette objekter, men også ændre opførslen af eksisterende objekter.

Prototyp-eegenskab kan ikke kun definere egenskaber og metoder for konstruktøren, men også tilføje egenskaber og metoder til lokale objekter.

Opret nye metoder

Opret nye metoder ved hjælp af eksisterende metoder

Man kan bruge prototype-attributten til at definere nye metoder for enhver eksisterende klasse, ligesom man håndterer sin egen klasse. For eksempel kan man huske Number-klassens toString() metode? Hvis man sender 16 som parameter til denne metode, vil den udskrive en hexadecimal streng. Hvis man sender 2 som parameter, vil den udskrive en binær streng. Man kan oprette en metode, der direkte kan konvertere et nummerobjekt til en hexadecimal streng. Det er meget simpelt at oprette denne metode:

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

I dette miljø peger nøgleordet this på en Number-instans, så man kan fuldt ud få adgang til Number's alle metoder. Med dette stykke kode kan man udføre følgende operationer:

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

TIY

Da tallet 15 er ens med F i hexadecimal, vil advarslen vise "F".

Omdøb eksisterende metoder

Man kan også navngive eksisterende metoder mere forståelige navne. For eksempel kan man tilføje to metoder til Array-klassen, enqueue() og dequeue(), som kun kalder de eksisterende push() og shift() metoder:

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

TIY

Tilføj metoder, der ikke er relateret til eksisterende metoder

Selvfølgelig kan man også tilføje metoder, der ikke er relateret til eksisterende metoder. For eksempel, antager man, at man vil vurdere positionen for et element i et array, og der er ingen lokale metoder, der kan gøre dette. Man kan nemt oprette følgende metode:

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

Denne metode indexOf() er ens med String-klassens同名metode, den søger efter hver element i arrayet, indtil den finder elementet, der er blevet sendt ind. Hvis den finder det samme element, returnerer den positionen for elementet, ellers returnerer den -1. Med denne definition kan vi skrive følgende kode:

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

TIY

Tilføj nye metoder til lokale objekter

Til sidst, hvis du vil tilføje en ny metode til hver lokal objekt i ECMAScript, skal du definere den på Object-objektets prototype-attribut. Som nævnt i tidligere kapitler arver alle lokale objekter Object-objektet, så ændringer i Object-objektet vil reflekteres i alle lokale objekter. For eksempel, hvis du vil tilføje en metode til at advare om objektets nuværende værdi, kan du bruge følgende kode:

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

TIY

Her arver String- og Number-objekterne showValue() metoden fra Object-objektet og kalder metoden på deres objekter, hvilket viser "hello" og "25".

Omdéfinition af eksisterende metoder

Som du kan definere nye metoder for eksisterende klasser, kan du også omdefinere eksisterende metoder. Som nævnt i tidligere kapitler er funktionens navn bare en pege på funktionen, så det er nemt at pege på andre funktioner. Hvis du ændrer en lokal metode, som toString(), hvad vil der ske?

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

Koden ovenfor er fuldt gyldig, og resultatet svarer til forventning:

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

TIY

Måske husker du, at Function-objektet i dette kapitel introducerede toString() metoden, som normalt uddeler kildekoden til funktionen. Ved at overridere denne metode kan du returnere en anden streng (i dette eksempel kan det returnere "Function code hidden"). Men hvad med den oprindelige funktion, som toString() peger på? Den vil blive indsamlet af det ubrugte lagerenhed回收program, fordi den er fuldstændigt forældet. Der er ingen måde at gendanne den oprindelige funktion på, så det er en forsigtig praksis at gemme dens pege på den, hvis du skal bruge den senere. Nogle gange kan du endda kalde den oprindelige metode i din nye metode:

Function.prototype.originalToString = Function.prototype.toString;
Function.prototype.toString = function() {
  if (this.originalToString().length > 100) {
    return "Funktionen er for lang til at vise.";
  } else {
    return this.originalToString();
  }
};

TIY

I dette stykke kode gemmer første linje referencen til den nuværende toString() metode i egenskaben originalToString. Derefter erstattes toString() metoden med en tilpasset metode. Den nye metode kontrollerer om længden af funktionens kildekode er større end 100. Hvis det er tilfældet, returnerer den en fejlmeddelelse om, at funktionens kode er for lang, ellers kalder den originalToString() metoden og returnerer kildekoden til funktionen.

Meget sen bindning (Very Late Binding)

Teknologisk set findes der ingen meget sen bindning. Denne bog bruger dette begreb til at beskrive et fænomen i ECMAScript, hvor metoder kan defineres efter objektet er instanceret. For eksempel:

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

TIY

I de fleste programmeringssprog skal metoder defineres før objekter instansieres. Her er metoden sayHi() tilføjet efter oprettelsen af en instans af Object-klasse. I traditionelle sprog har man aldrig hørt om denne operation, og man har heller ikke hørt om, at metoden automatisk tildeler Object-objektets instans og kan bruges med det samme (på det næste linje).

Bemærk:Det anbefales ikke at bruge meget sen bindning, da det er svært at spore og registrere det. Dog bør man stadig være opmærksom på denne mulighed.