Ändra objekt i ECMAScript
- Föregående sida Definiera klass eller objekt
- Nästa sida Exempel på arvsmekanism
Genom att använda ECMAScript kan man inte bara skapa objekt, utan också ändra beteendet hos befintliga objekt.
Prototyp-attribut kan inte bara definiera egenskaper och metoder för konstruktörer, utan kan också lägga till egenskaper och metoder till lokala objekt.
Skapa nya metoder
Skapa nya metoder genom befintliga metoder
Man kan använda prototype-attributet för att definiera nya metoder för alla befintliga klasser, precis som man behandlar sina egna klasser. Till exempel, minns du Number-klassens toString() metod? Om man skickar in 16 som parameter, skriver den ut en hexadecimalsträng. Om man skickar in 2 som parameter, skriver den ut en binärsträng. Man kan skapa en metod som konverterar ett nummerobjekt direkt till en hexadecimalsträng. Att skapa denna metod är mycket enkel:
Number.prototype.toHexString = function() { return this.toString(16); };
I detta miljö, pekar nyckeln this på ett Number-instans, så man kan helt tillgång till alla metoder i Number. Med denna kod kan man utföra följande operationer:
var iNum = 15; alert(iNum.toHexString()); //Visa "F"
Eftersom talet 15 är lika med F i hexadecimal, kommer varningen att visa "F".
Byt namn på befintliga metoder
Man kan också ge befintliga metoder mer förståeliga namn. Till exempel kan man lägga till två metoder enqueue() och dequeue() till Array-klassen, som bara anropar befintliga push() och shift() metoder:
Array.prototype.enqueue = function(vItem) { this.push(vItem); }; Array.prototype.dequeue = function() { return this.shift(); };
Lägg till metoder som inte har något att göra med befintliga metoder
Naturligtvis kan man lägga till metoder som inte har något att göra med befintliga metoder. Till exempel, antar vi att vi vill avgöra positionen för ett element i en array, det finns ingen lokal metod för att göra detta. Vi kan enkelt skapa följande metod:
Array.prototype.indexOf = function (vItem) { for (var i=0; i<this.length; i++) { if (vItem == this[i]) { return i; } } return -1; }
Denna metod indexOf() är identisk med den同名metoden i String-klassen, den söker varje element i arrayen tills den hittar ett element som matchar det som skickas in. Om ett liknande element hittas, returneras dess position, annars returneras -1. Med denna definition kan vi skriva följande kod:
var aColors = new Array("red","green","blue"); alert(aColors.indexOf("green")); //Visar "1"
Lägg till nya metoder för lokala objekt
Till slut, om du vill lägga till en ny metod för varje lokal objekt i ECMAScript, måste du definiera den på Object-objektets prototype-attribut. Som vi har talat om tidigare är alla lokala objektverken Object-objektet, så alla förändringar du gör på Object-objektet kommer att påverka alla lokala objekt. Till exempel, om du vill lägga till en metod som visar objektets nuvarande värde med varning, kan du använda följande kod:
Object.prototype.showValue = function () { alert(this.valueOf()); }; var str = "hello"; var iNum = 25; str.showValue(); //Visar "hello" iNum.showValue(); //Visar "25"
Här har String- och Number-objekten ärver showValue() -metoden från Object-objektet och anropar den på sina respektive objekt, vilket visar "hello" och "25".
Omdefiniera befintliga metoder
Liksom att du kan definiera nya metoder för befintliga klasser kan du också omdefiniera befintliga metoder. Som nämnts i tidigare kapitel är ett funktionsnamn bara en pekare till en funktion, så det kan enkelt peka på andra funktioner. Vad händer om du ändrar en lokal metod, som toString()?
Function.prototype.toString = function() { return "Function code hidden"; }
Koden ovan är helt giltig och körresultatet är som förväntat:
function sayHi() { alert("hi"); } alert(sayHi.toString()); //Visar "Function code hidden"
Många av oss minns kanske, i kapitlet om Function-objektet nämndes att toString() -metoden vanligtvis skriver ut källkoden för en funktion. Genom att överskriva denna metod kan du returnera en annan sträng (i detta fall kan du returnera "Function code hidden"). Men vad händer med den ursprungliga funktionen som toString() pekar på? Den kommer att återvinnas av minnesåtervinningssystemet eftersom den är helt övergiven. Det finns ingen metod för att återställa den ursprungliga funktionen, så det är säkrast att lagra dess pekare innan du överskriver den ursprungliga metoden, för att kunna använda den senare. Ibland kan du till och med anropa den ursprungliga metoden i den nya metoden:
Function.prototype.originalToString = Function.prototype.toString; Function.prototype.toString = function() { if (this.originalToString().length > 100) { return "Funktionen är för lång för att visa."; } else { return this.originalToString(); } };
I detta kodexempel sparar det första raden en referens till den nuvarande toString() -metoden i egenskapen originalToString. Sedan ersätts toString() -metoden med en anpassad metod som kontrollerar om längden på funktionens källkod är större än 100. Om det är så, returneras ett felmeddelande som anger att funktionens kod är för lång, annars anropas originalToString() -metoden och returnerar källkoden för funktionen.
Extremt sent bindning (Very Late Binding)
Tekniskt sett finns det ingen extremt sent bindning. Denna bok använder termen för att beskriva ett fenomen i ECMAScript, där det är möjligt att definiera metoder efter att objektet har instantierats. Till exempel:
var o = new Object(); Object.prototype.sayHi = function () { alert("hi"); }; o.sayHi();
I de flesta programmeringsspråk måste objektets metoder definieras innan objektet instantieras. Här läggs metoden sayHi() till efter att en instans av Object-klassen har skapats. I traditionella språk har man inte hört talas om denna operation, och man har inte hört talas om att metoden automatiskt tilldelas objektets instans och kan användas omedelbart (på nästa rad).
Observera:Det rekommenderas inte att använda extremt sent bindningsmetoder eftersom det är svårt att spåra och registrera dem. Men det bör fortfarande förstås denna möjlighet.
- Föregående sida Definiera klass eller objekt
- Nästa sida Exempel på arvsmekanism