Avatar billede nyp Nybegynder
12. marts 2005 - 14:16 Der er 12 kommentarer og
1 løsning

Object.prototype

Hvordan opretter man nye property på objekter, jeg forestillede mig noget i retning af nedenstående, som virker fint i Firefox men ikke i ie?


<html>
<head>
<title>test Object</title>

<script>


Object.prototype.addTag = function(tag)
{
  tagObj=document.createElement(tag);
  this.appendChild(tagObj);
}

function start()
{
a=document.getElementById("container");
a.addTag("div");
alert(a.innerHTML);

}

onload=start;

</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
Avatar billede olebole Juniormester
12. marts 2005 - 14:30 #1
<ole>

Det er fordi, et div er et HTML-element ... ikke et JavaScript-objekt. Du kan kun prototype på HTML-elementer i Moz

/mvh
</bole>
Avatar billede olebole Juniormester
12. marts 2005 - 14:31 #2
Det blev lidt utydeligt  :)
"Det er kun i Moz, du kan prototype på HTML-elementer" - mente jeg
Avatar billede olebole Juniormester
12. marts 2005 - 14:38 #3
... og i virkeligheden burde man skrive således i Moz:
  Element.prototype.addTag = function(tag) {

- eller:
  HTMLElement.prototype.addTag = function(tag) {

Som jeg læser standarderne, må det, du har skrevet, ikke kunne fungere - og er således en bug i Gecko-motoren  :)
Avatar billede olebole Juniormester
12. marts 2005 - 15:06 #4
Sorry, der var lige nogle ting, jeg skulle ordne ... jeg fortsætter, hvor jeg slap  :)

Nu ser jeg dit eget eksempel som ..... et eksempel. Jeg ville nok ikke begynde på det store forkromede OOP/prototype cirkus, men i en lidt større sammenhæng er det en kanon teknik at benytte sig af. I sådan et senarium, kunne du gøre noget à la:

<script type="text/JavaScript">
function MakeMyObjects(elm) {
    this.element = elm;
    this.addTag = this.fn_addTag;
    return this;
}
var _p = MakeMyObjects.prototype;
_p.fn_addTag = function(tag) {
    var tagObj = document.createElement(tag);
    this.element.appendChild(tagObj);
    return tagObj
}

var myObjs = {};
window.onload = function() {
    var aDiv = document.getElementsByTagName("div");
    for (i=0,j=aDiv.length; i<j; i++) {
        myObjs[aDiv[i].id] = new MakeMyObjects(aDiv[i]);
    }
   
    var bla = myObjs.container.addTag("div");
    bla.innerHTML = "Noget et eller andet";
}
</script>

- derved lægger du alle de elementer, der skal have den ny property/metode som properties på objektet 'myObjs' - og med elementernes ID som property-names.

Da vi jo har et div, der hedder 'container', kan du altså kalde den nye metode med:
    var bla = myObjs.container.addTag("div");
- hvor 'bla' så vil indeholde en reference til det nyoprettede div-element.

Det er én måde at gøre det på, men der kan vælges mange andre. Den endelige fremgangsmåde beror på, hvad der skal opnås og hvordan koden i øvrigt er opbygget.
Avatar billede olebole Juniormester
12. marts 2005 - 15:13 #5
En simplere måde at skrive netop dette eksempel på kunne være:

<script type="text/JavaScript">
function MakeMyObjects(elm) {
    this.element = elm;
    this.addTag = function(tag) {
        var tagObj = document.createElement(tag);
        this.element.appendChild(tagObj);
        return tagObj
    }
    return this;
}

var myObjs = {};
window.onload = function() {
    var aDiv = document.getElementsByTagName("div");
    for (i=0,j=aDiv.length; i<j; i++) {
        myObjs[aDiv[i].id] = new MakeMyObjects(aDiv[i]);
    }
   
    var bla = myObjs.container.addTag("div");
    bla.innerHTML = "Noget et eller andet";
}
</script>

- men nu begyndte du selv at tale om prototyping, så derfor gav jeg dig det første eksempel. Det viser også den mest overskuelige opbygning til større OOP-applikationer - men til helt små, simple ting, kan nr. 2 være den fikseste (hvis det altså overhovedet er værd at begynde at OOP'e i sådan en situation).
Avatar billede olebole Juniormester
12. marts 2005 - 15:18 #6
PS: Hvis du undrer dig lidt over mine for-løkker:
    for (i=0,j=aDiv.length; i<j; i++) {
- så er det bare en hurtigere måde at skrive dette:
    for (i=0; i<aDiv.length; i++) {

På den måde henter jeg kun dimensionen af arrayet én gang - hvor jeg ellers ville hente værdien ved hvert gennemløb af løkken.
Flueknebberi? Nuvel, ved store applikationer gælder det om at tænke over hver linie og prøve at optimere, hvor det er muligt. Derfor er jeg ved at anlægge en ny kodestil, hvad for-løkker angår  :)

Så er der zq heller ikke mere for den 25-øre, før du melder tilbage med opfølgende spm  ;o)
Avatar billede nyp Nybegynder
12. marts 2005 - 15:20 #7
Tak, det ser spændende ud, jeg vil kikke på det, jeg omskrev mit eksempel til nedenstående som fungerer, vil du lægge et svar?

Object.prototype.addTag = function(dest,tag)
{
  this.oElement= document.getElementById(dest);
  tagObj=document.createElement(tag);
  this.oElement.appendChild(tagObj);
}

function start()
{
a=new Object;

a.addTag("container","div");
alert(a.oElement.innerHTML);
}
Avatar billede olebole Juniormester
12. marts 2005 - 15:39 #8
Hmmmm .... det er ikke en god løsning. Du skal huske på, at du klistrer denne nye metode på alle nye objekter - uanset om den giver mening på det pågældende objekt eller ej. Det er skidt OOP  :)
Du kan prøve dette:

function start() {
    a=new Object;
   
    a.addTag("container","div");
    alert(a.oElement.innerHTML);
   
    var o = new Object();
    o.dreng = "Ib";
    o.dyr = "Gnu";
   
    for (x in o) {
        alert(x + " => " + o[x])
    }
}

Hvis mit objekt 'o' beskriver en person og vekommendes foretrukne sexpartner (hø-hø), så er det jo noget rod, at dette person-objekt har en metode, der kan oprette et div i 'hans innerHTML'. Det giver nada mening - og en høj grad af 'naturidentisk' logik er netop, hvad der kendetegner (god) OOP  ;o)

Jeg må derfor opfordre dig til at undlade at prototype på generelle konstruktorer - og sørge for at holde en meget høj grad af logik i koden.
Avatar billede olebole Juniormester
12. marts 2005 - 15:44 #9
PS: Lige et par andre ting:
1. Husk at angive 'type' i script-tags ... det er påkrævet.
2. Hvis der er tale om lokale variabler, der ikke har noget at gøre udenfor en given funktion, bør de erklæres med nøgleordet 'var' i funktionen.
3. Husk parentesen, når du instantierer nye objekter - new Object() ... det er påkrævet
Avatar billede nyp Nybegynder
12. marts 2005 - 15:48 #10
Nej, nu har jeg jeg fundet ud af hvad du mener og det er perfekt!!
Avatar billede olebole Juniormester
12. marts 2005 - 16:12 #11
Squide godt  ;o)

Du _kan_ godt prototype på indbyggede konstruktorer, men du vil altid løbe ind i det 'problem', at nye properties og metoder eksponeres, når man bladrer strukturen igennem, som jeg viste før.
F.eks. har PHP jo en udmærket funktion, der hedder 'in_array()', der kan checke, om et array indeholder en bestemt værdi - og returnere den plads, hvorpå det i så fald står. Den kan vi eftergøre i JS på denne måde:

function fn_inArray(val) {
    var inx=0, len=this.length;
    while (this[inx]!=val && inx<len) inx++;
    return (inx<this.length)? inx : -1;
}
Array.prototype.inArray = fn_inArray;

var bla = new Array("hest", "ko", "kylling", "gnu");
alert( bla.inArray("kylling") );  // Returnerer 2
alert( bla.inArray("pomfrit") );  // Returnerer -1

- dog vil du rende ind i samme problem som før, hvis du bladrer array'et igennem i en for/in-løkke:

var a = new Array();
a["dreng"] = "Ib";
a["dyr"] = "Hest";
for (x in a) {
    alert(x + " => " + a[x])
}

Det er noget, man skal være meget opmærksom på - og er man det, kan man godt udvide indbyggede datastrukturer ved prototyping.
Læg også mærke til, at vi i dette tilfælde godt kan forsvare logikken. Det er en metode, der giver mening på ethvert array  :)

PS: Jeg fik aldrig sagt det, så: Tak for points  :)
Avatar billede olebole Juniormester
12. marts 2005 - 16:44 #12
Da denne tråd i forvejen har udviklet sig i retning af noget tutorial/artikel-agtigt, kan du ligeså godt lære en sidste ting  :)

Brugen af 'in_array()' eller min JS-erstatning er ikke noget, man skal overdrive - da det ikke er en effektiv måde at søge på.
Hvis jeg skal fylde et array dynamisk - og ved, at jeg ofte skal spørge, om et bestemt element eksisterer, bør jeg i stedet oprette en kontrol-struktur. Hvis jeg f.eks. vil fylde et array med ID'et på de divs på siden, der har et ID, der begynder med 'hest_', kunne jeg skrive:

var a = new Array();
var aDivs = document.getElementsByTagName("div");
for (i=0,j=aDivs.length; i<j; i++) {
    if (aDivs[i].id.indexOf("hest_")!=-1) a.push( aDivs[i].id );
}

- så kunne jeg skrive:

var pos = a.inArray("hest_123");
if ( pos ) {
  // Hvis div'et eksisterer, så gør noget ved det
    document.getElementById(pos).style.color = "red";
}

Skal dette gøres mange gange, er det en ineffektiv metode. Så er dette langt hurtigere:

var aContrl = new Array();
var aDivs = document.getElementsByTagName("div");
for (i=0,j=aDivs.length; i<j; i++) {
    if (aDivs[i].id.indexOf("hest_")!=-1) {
        aContrl[ aDivs[i].id ] = 1;
}

- så kan jeg skrive:

if (aContrl["hest_123"]) {
  // Hvis div'et eksisterer, så gør noget ved det
  document.getElementById("hest_123").style.color = "red";
}

Nu kan jeg bruge et ID som nøglen i kontrol-array'et, hvilket giver direkte tilgang - og dermed en langt hurtigere søgning.

I dette specifikke tilfælde kunne det dog gøres endnu hurtigere med:

var a = new Array();
var aDivs = document.getElementsByTagName("div");
for (i=0,j=aDivs.length; i<j; i++) {
    if (aDivs[i].id.indexOf("hest_")!=-1) {
        a[ aDivs[i].id ] = aDivs[i];
}

- og:

var elm = a["hest_123"];
if (elm) {
  // Hvis div'et eksisterer, så gør noget ved det
  elm.style.color = "red";
}

... slut - prut  :)
Avatar billede olebole Juniormester
12. marts 2005 - 16:46 #13
Det første eksempel i seneste kommentar var forkert. Der skulle stå:

var a = new Array();
var aDivs = document.getElementsByTagName("div");
for (i=0,j=aDivs.length; i<j; i++) {
    if (aDivs[i].id.indexOf("hest_")!=-1) a.push( aDivs[i].id );
}

- så kunne jeg skrive:

var pos = a.inArray("hest_123");
if ( pos ) {
  // Hvis div'et eksisterer, så gør noget ved det
    document.getElementById( a[pos] ).style.color = "red";
}
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester

IT-JOB