[ Web Proxy ]
URL:
Viewing: https://da.javascript.info/function-prototype [Back]  [Original]

F.prototype
DA

Vi nsker at gre dette open source-projekt tilgngeligt for folk over hele verden.

Hjlp med at overstte indholdet af denne tutorial til dit sprog!

    Sg p Javascript.info:
    Sg i tutorialen:
    Lyst temaMrkt tema
    DanskEnglishEspaolFranaisIndonesiaItalianoTrkeOzbek

    Du husker nok at nye objekter kan oprettes med en konstruktr funktion, som f.eks. new F().

    Hvis F.prototype er et objekt, s bruger new-operatoren det til at stte [[Prototype]] for det nye objekt.

    Bemrk venligst:

    JavaScript har haft nedarvning fra prototype fra begyndelsen. Det er en af sprogets kernetrk.

    Men i gamle dage var der ikke nogen direkte adgang til det. Den eneste ting der virkede plideligt var en "prototype" egenskab i konstruktr funktioner som vi beskriver i dette kapitel. S der er mange scripts der stadig bruger denne tilgang.

    Bemrk at udtrykket F.prototype her betyder en regulr egenskab kaldet "prototype" p objektet F. Det lyder som noget tt p selve begrebet prototype, men her mener vi faktisk bare en regulr egenskab med det navn.

    Her er et eksempel:

    let animal = {
      eats: true
    };
    
    function Rabbit(name) {
      this.name = name;
    }
    
    Rabbit.prototype = animal;
    
    let rabbit = new Rabbit("Hvid kanin"); //  rabbit.__proto__ == animal
    
    alert( rabbit.eats ); // true

    Nr vi skriver Rabbit.prototype = animal betyder det bogstaveligt talt: Nr en ny Rabbit skabes, s srg for at dens [[Prototype]] sttes til animal.

    Det resulterer i flgende:

    []

    P billedet er "prototype" en horisontal pil, hvilket betyder en regulr egenskab, og [[Prototype]] er en lodret pil, betyder nedarvning af rabbit fra animal.

    F.prototype bruges kun ved new F

    Egenskaben F.prototype bruges kun nr new F kaldes, og den stter [[Prototype]] p det nye objekt.

    Hvis F.prototype-egenskaben ndres efter objektet er skabt (F.prototype = <another object>), s vil nye objekter skabt med new F have et andet objekt som [[Prototype]], mens eksisterende objekter beholder det gamle.

    Standard F.prototype, konstruktr egenskab

    Alle funktioner har egenskaben "prototype" selvom vi ikke angiver den.

    Den standard "prototype" er et objekt med den ene egenskab constructor som peger tilbage p funktionen selv.

    Som dette:

    function Rabbit() {}
    
    /* standard prototype
    Rabbit.prototype = { constructor: Rabbit };
    */
    []

    Det kan vi tjekke ved at se p constructor egenskaben:

    function Rabbit() {}
    // som standard:
    // Rabbit.prototype = { constructor: Rabbit }
    
    alert( Rabbit.prototype.constructor == Rabbit ); // true

    Hvis vi ikke gr noget andet vil egenskaben constructor vre tilgngelig for alle kaniner gennem [[Prototype]]:

    function Rabbit() {}
    // som standard:
    // Rabbit.prototype = { constructor: Rabbit }
    
    let rabbit = new Rabbit(); // nedarver fra {constructor: Rabbit}
    
    alert(rabbit.constructor == Rabbit); // true (fra prototype)
    []

    Vi kan bruge constructor egenskaben til at skabe et nyt objekt med samme konstruktr som det eksisterende objekt.

    Som her:

    function Rabbit(name) {
      this.name = name;
      alert(name);
    }
    
    let rabbit = new Rabbit("Hvid kanin");
    
    let rabbit2 = new rabbit.constructor("Sort kanin");

    Det er praktisk nr vi har et objekt og ikke ved hvilken konstruktr det blev skabt med (f.eks. hvis det kommer fra en 3rd party bibliotek), og vi skal skabe et andet objekt af samme type.

    Men den vigtigste ting at huske p om "constructor" er at

    JavaScript sikrer ikke selv at vrdien i "constructor" er korrekt.

    Ja, den eksisterer i standard "prototype" for funktioner, men det er det. Hvad der sker senere det er helt op til os.

    Det glder srligt, hvis vi erstatter standard prototypen i sin helhed, s vil der ikke lngere vre nogen "constructor" i den.

    For eksempel:

    function Rabbit() {}
    Rabbit.prototype = {
      jumps: true
    };
    
    let rabbit = new Rabbit();
    alert(rabbit.constructor === Rabbit); // false

    S for at beholde den korrekte "constructor" kan vi vlge at tilfje/fjerne egenskaber til standard "prototype" i stedet for at overskrive hele prototypen:

    function Rabbit() {}
    
    // Overskriver ikke Rabbit.prototype helt
    // vi tilfjer bare noget til den
    Rabbit.prototype.jumps = true
    // standard Rabbit.prototype.constructor er bevaret

    Alternativt kan du genskabe egenskaben constructor manuelt, hvis du erstatter hele prototypen:

    Rabbit.prototype = {
      jumps: true,
      constructor: Rabbit
    };
    
    // nu er constructor rigtig igen, fordi vi tilfjede den tilbage til objektet

    Opsummering

    I dette kapitel beskrev vi kort mden at stte en [[Prototype]] for objekter skabt via en konstruktr funktion. Senere vil vi se mere avancerede programmeringsmnstre, der bygger p det.

    Alt er egentlig ganske enkelt. Her er nogle f bemrkninger for at gre tingene helt klart:

    • Egenskaben F.prototype (ikke at forveksle med [[Prototype]]) stter [[Prototype]] p nye objekter nr new F() kaldes.
    • Vrdien af F.prototype br enten vre et objekt eller null: andre vrdier virker ikke.
    • Egenskaben "prototype" har kun denne specielle effekt nr den er sat p en konstruktr funktion, og kaldes med new.

    P regulre objekter er prototype ikke noget specielt:

    let user = {
      name: "John",
      prototype: "Bla-bla" // magien er vk!
    };

    Som standard har alle funktioner F.prototype = { constructor: F }, s vi kan f konstruktren af et objekt ved at tilg dets "constructor" egenskab.

    Opgaver

    vigtighed: 5

    I koden nedenfor opretter vi new Rabbit, og forsger derefter at ndre dens prototype.

    I starten har vi flgende kode:

    function Rabbit() {}
    Rabbit.prototype = {
      eats: true
    };
    
    let rabbit = new Rabbit();
    
    alert( rabbit.eats ); // true
    1. Vi har tilfjet endnu en streng (fremhvet). Hvad viser alert nu?

      function Rabbit() {}
      Rabbit.prototype = {
        eats: true
      };
      
      let rabbit = new Rabbit();
      
      Rabbit.prototype = {};
      
      alert( rabbit.eats ); // ?
    2. Og hvis koden ser sledes ud (har erstattet en linje)?

      function Rabbit() {}
      Rabbit.prototype = {
        eats: true
      };
      
      let rabbit = new Rabbit();
      
      Rabbit.prototype.eats = false;
      
      alert( rabbit.eats ); // ?
    3. Og, hvad med denne her (har erstattet en linje)?

      function Rabbit() {}
      Rabbit.prototype = {
        eats: true
      };
      
      let rabbit = new Rabbit();
      
      delete rabbit.eats;
      
      alert( rabbit.eats ); // ?
    4. Sidste variant?

      function Rabbit() {}
      Rabbit.prototype = {
        eats: true
      };
      
      let rabbit = new Rabbit();
      
      delete Rabbit.prototype.eats;
      
      alert( rabbit.eats ); // ?
    lsning

    Svarene er:

    1. true.

      Tildelingen til Rabbit.prototype stter [[Prototype]] for nye objekter, men pvirker ikke eksisterende objekter. S rabbit har stadig den gamle prototype, hvor eats er true.

    2. false.

      Objekter bliver tildelt med reference til det oprindelige objekt. Objektet fra Rabbit.prototype er ikke kopieret, det er stadig et enkelt objekt refereret bde af Rabbit.prototype og af [[Prototype]] p rabbit.

      S nr vi ndrer dets indhold via n reference, er det synligt via den anden reference.

    3. true.

      Alle delete operationer udfres direkte p objektet. Her forsger delete rabbit.eats at fjerne eats egenskaben fra rabbit, men det har ikke den egenskab. S operationen har ingen effekt.

    4. undefined.

      Egenskaben eats er slettet fra prototypen, den eksisterer ikke lngere.

    vigtighed: 5

    Forestil dig, vi har et vilkrligt objekt obj, skabt af en konstruktr funktion vi ved ikke hvilken, men vi vil gerne skabe et nyt objekt med samme konstruktr.

    Kan vi gre det sdan?

    let obj2 = new obj.constructor();

    Giv et eksempel p en konstruktr funktion for obj som lader sdan kode virke korrekt. Og et eksempel som gr det forkert.

    lsning

    Vi kan bruge denne tilgang hvis vi er sikre p at "constructor" egenskaben har den korrekte vrdi.

    For eksempel, hvis vi ikke rrer ved standard "prototype", s virker denne kode altid:

    function User(name) {
      this.name = name;
    }
    
    let user = new User('Jan');
    let user2 = new user.constructor('Helene');
    
    alert( user2.name ); // Helene (virker!)

    Det virker fordi User.prototype.constructor == User.

    Men hvis en overskriver User.prototype uden at genskabe constructor som reference til User, s vil det fejle.

    For eksempel:

    function User(name) {
      this.name = name;
    }
    User.prototype = {}; // (*)
    
    let user = new User('Jan');
    let user2 = new user.constructor('Helene');
    
    alert( user2.name ); // undefined

    Hvorfor er user2.name undefined?

    Sdan her virker new user.constructor('Helene'):

    1. Frst kigger den efter constructor i user. Intet fundet.
    2. Derefter flger den prototypen. Prototypen af user er User.prototype, og den har ogs ingen constructor (fordi vi glemte at genskabe den!).
    3. Gr videre op i kden, User.prototype er et almindeligt objekt, og dens prototype er den indbyggede Object.prototype.
    4. Til sidst, for den indbyggede Object.prototype, findes der en indbygget Object.prototype.constructor == Object. S bruges denne.

    Til sidst har vi alts noget der oversat ser ud som let user2 = new Object('Helene').

    Helt sikkert ikke det vi vil. Vi nsker at skabe new User, ikke new Object. Det er resultatet af den manglende constructor.

    (Bare, i det tilflde, at du er nysgerrig: Kaldet til new Object(...) konverterer dets argument til et objekt. Det er en teoretisk ting, i praksis kalder ingen new Object med en vrdi, og generelt bruger vi ikke new Object til at lave objekter).

    Tutorial-oversigt

    Kommentarer

    ls dette fr du kommenterer
    • Hvis du har forslag til forbedringer - s opret venligst et GitHub-issue eller en pull request i stedet for at kommentere.
    • Hvis du ikke forstr noget i artiklen - s uddyb venligst.
    • For at indstte f ord kode, brug <code>-taggen, for flere linjer - omslut dem i <pre>-tag, for mere end 10 linjer - brug en sandbox (plnkr, jsbin, codepen)

    Web Proxy Viewer  |  New URL  |  Original Page