MDN wants to talk to developers like you: https://qsurvey.mozilla.com/s3/8d22564490d8

Object-orienterad JavaScript för nybörjare

Med grunderna ur vägen, kommer vi nu att fokusera på objektorienterad  JavaScript (OOJS) - den här artikeln presenterar teorinen för grundläggande syn på objektorienterad programmering (OOP), sedan förklarar vi hur JavaScript emulerar objektklasser via konstruktorfunktioner och hur man skapar objektinstanser.

Förutsättningar: Grundläggande datakunskap, en grundläggande förståelse för HTML och CSS, och JavaScript (se First steps och Building blocks) och OOJS grunderna (see Introduction to objects).
Mål: Att förstå den grundläggande teorin bakom objektorienterad programmering, hur detta relaterar till JavaScript ( "där allt är objekt"), och hur man skapar konstruktörer och objekt instanser.

Objektorienterad programmering från 10.000 meter

Till att börja med, låt oss ge dig en förenklad, hög nivå vy, över vad Objektorienterad programmering (OOP) är.Vi säger förenklat, eftersom OOP snabbt kan bli mycket komplicerat, och ge det en fullständig genomgång, hör och nu, skulle förmodligen förvirra mer än hjälp. Den grundläggande idén med OOP är att vi använder objekt för att modellera verkliga saker som vi vill representera i våra program, och/eller ge ett enkelt sätt att komma åt funktioner som annars skulle vara svårt eller omöjligt att använda sig av.

Objekt kan innehålla relaterade data och kod, som representerar information om det du försöker att modellera och funktionalitet eller beteende som du vill att den ska ha. Objektdata (och ofta, funktioner) kan lagras prydligt (det officiella order är inkapslad) i ett objekt paket(Som kan ges ett specifikt namn för att referera till, som ibland kallas ett namnutrymme ), vilket gör det lätt att strukturera och tillgång; objekt används också ofta som datalager som lätt kan skickas över nätverket.

Definiera en objekt mall

Låt oss betrakta ett enkelt program som visar information om elever och lärare på en skola. Här ska vi titta på OOP teorin i allmänhet, inte i samband med något specifik programmeringsspråk.

För att börja detta, skulle vi gå tillbaka till vår person objekttyp från vår första objekt artikel, som definierar den generiska data och funktionaliteten hos en person. Det finns massor av saker du kan veta om en person (sin adress, höjd, skostorlek, DNA-profil, passnummer , betydande personlighetsdrag ...), men i detta fall är vi bara intresserade av visar deras namn, ålder, kön och intressen. Vi vill också kunna skriva en kort introduktion om dem utifrån dessa data, och få dem att säga hej. Detta kallas abstraktion - att skapa en enkel modell av en mer komplex sak som representerar de viktigaste aspekterna på ett sätt som är lätt att arbeta med för vår programmets syften.

I vissa OOP språk är det denna generiska objekt typ definition, som kallas en klass (JavaScript använder en annan mekanism och terminologi, som du ser nedan) - vi ser inte på det som ett objekt, utan det en mall som definierar vilka egenskaper ett objekt borde ha.

Skapa faktiska objekt

Från vår klass, kan vi skapa objektinstanser - objekt som innehåller data och funktioner som definieras i klassen. Från vår Person klass, kan vi nu skapa några verkliga människor:

När ett objekt instans skapas från en klass, exekveras klassens konstruktorfunktion för att skapa den. Denna process för att skapa en objektinstans från en klass kallas instansiering - objektinstansen instansieras från klassen.

Specialist klasser

I det här fallet vill vi inte använda oss av generiska människor, istället, vill vi ha lärare och elever, som båda är specifika typer av människor. I OOP, kan vi skapa nya klasser baserade på andra klasser — dessa nya barn-klasser kan ärva data och kod egenskaper i en förälder-klass, så att du kan återanvända egenskaper som är gemensam för alla objekttyper i stället för att tvingas kopiera dem. Där egenskaperna skiljer sig mellan klasser, kan du definiera specialiserad funktionallitet direkt på dem, efter behov.

Detta är verkligen användbart - lärare och elever har många gemensamma egenskaper såsom namn, kön och ålder, så det är användbart att bara behöva definiera dessa egenskaper en gång. Du kan också definiera samma egenskap separat i olika klasser, eftersom varje definition av den egenskapen kommer att vara i ett annan namnområde. Till exempel kan en student hälsning ha formen "Yo, jag är [firstname ]" (t.ex. Yo, jag är Sam), medan en lärare kan använda något mer formell, till exempel "Hej, mitt namn [Prefix ] [lastname ], och jag undervisar [Subject]." (T.ex. Hej, mitt namn Mr Griffiths, och jag undervisar kemi).

Obs! Finare ord för möjligheten av flera objekttyper för att implementera samma egenskap är polymorfism.

Du kan nu skapa objektinstanser från dina barn-klasser. Till exempel:

I resten av artikeln kommer vi att börja titta på hur OOP teorin kan omsättas i praktiken i JavaScript.

Konstruktörer och objektinstanser

Somliga hävdar att JavaScript inte är ett sannt objektorienterat språk - till exempel har den inte en class uttalande för att skapa klasser som många OO språk. JavaScript använder istället specialfunktioner som kallas konstruktorfunktioner för att definiera objekt och deras egenskaper. De är användbara eftersom du ofta stöter på situationer där du inte vet hur många objekt du vill skapa; konstruktörer ger dig möjlighet att skapa så många objekt som du behöver på ett effektivt sätt, fästa data och funktioner till dem efter behov.

När ett nytt objekt instans skapas från en konstruktorfunktion är inta alla egenskaper kopierade över till det nya objektet som i "klassiska" OO språk — istället är egenskaperna kopplad via en referenskedja som kallas för prototypkedja
(se Object prototypes). Så det här är inte sant instansiering, strikt talat - JavaScript använder en annan mekanism för att dela egenskaper mellan objekt.

Obs! Att inte vara "klassiska OOP" är inte nödvändigtvis en dålig sak; som nämnts ovan, kan OOP snabbt bli myckt komplext och JavaScript har några trevliga sätt att dra nytta av OO egenskaper utan att behöva gå för mycket in på djupet.

Låt oss undersöka hur vi skapa klasser via konstruktörer och skapa objekt utifrån från dem i JavaScript. Först och främst vill vi dig att göra en ny lokal kopia av oojs.html file filen vi såg i vår första Objects artikeln.x

Ett enkelt exempel

  1. Låt oss börja med att titta på hur du kan definiera en person med en normal funktion. Lägg till den här funktionen under den befintliga koden:
    function createNewPerson(name) {
      var obj = {};
      obj.name = name;
      obj.greeting = function() {
        alert('Hi! I\'m ' + this.name + '.');
      };
      return obj;
    }
  2. Du kan nu skapa en ny person genom att anropa den här funktionen - prova följande rader i webbläsarens JavaScript-konsol:
    var salva = createNewPerson('Salva');
    salva.name;
    salva.greeting();
    Detta fungerar tillräckligt bra, men det är lite långtradigt; om vi vet att vi vill skapa ett objekt, varför måste vi uttryckligen skapa ett nytt tomt objekt och returnera den? Lyckligtvis get JavaScript oss en praktisk genväg i form av konstruktorfunktioner - låt oss skapa en nu!
  3. Byt ut din tidigare funktion med följande:
    function Person(name) {
      this.name = name;
      this.greeting = function() {
        alert('Hi! I\'m ' + this.name + '.');
      };
    }

Konstruktorfunktionen är JavaScript's version av en klass. Du ser att den har alla egenskaper du förväntar dig av en funktion, även om den inte returnerar något eller uttryckligen skapa ett objekt— i princip bara definierar den egenskaper och metoder. Du ser också att nyckelordet this används här — I princip säger this att när ett av dessa objektinstanser skapas kommer objektets namn egendom vara lika med namn värdet som skickas till konstruktören via anfop och även greeting () metoden kommer också att använda namnets värde.

Obs! En konstruktörs funktionsnamn börjar oftast med stor bokstav - denna konvention används för att göra konstruktorfunktioner lättare att känna igen i kod.

Så hur ska vi kalla en konstruktör att skapa några objekt?

  1. Lägg till följande rader under din tidigare kod inlägg:
    var person1 = new Person('Bob');
    var person2 = new Person('Sarah');
  2. Spara din kod och ladda om den i webbläsaren och försök att skriva in följande rader i din textinmatning :
    person1.name
    person1.greeting()
    person2.name
    person2.greeting()

Häftigt! Du kommer nu se att vi har två nya objekt på sidan, som vart och ett lagras under olika namnutrymmen - när du tillgår deras egenskaper och metoder, måste du anropa dem med person1 eller person2; De är prydligt bort packade så att de inte kollidera med andra funktioner. de har dock samma name egendom och greeting() metod tillgänglig. Obs tatt de använder sitt eget name värde som tilldelades till dem när de skapades; Detta är en anledning till varför det är mycket viktigt att använda this, så de kommer att använda sina egna värden, och inte något annat värde.

Låt oss titta på konstruktorfunktionens anrop igen:

var person1 = new Person('Bob');
var person2 = new Person('Sarah');

I varje fall är det new nyckelordet som används för att tala om för webbläsaren vi vill skapa en ny objekt-instans, följt av funktionsnamnet med de nödvändiga parametrar som finns inom parentes, resultatet lagras sedan i en variabel - det liknar mycket hur en standard funktionen anropas. Varje instans skapas enligt denna definition:

function Person(name) {
  this.name = name;
  this.greeting = function() {
    alert('Hi! I\'m ' + this.name + '.');
  };
}

Efter att de nya objekten har skapats, har person1 och Person2 variabler som innehåller följande objekt:

{
  name: 'Bob',
  greeting: function() {
    alert('Hi! I\'m ' + this.name + '.');
  }
}

{
  name: 'Sarah',
  greeting: function() {
    alert('Hi! I\'m ' + this.name + '.');
  }
}

Observera att när vi kallar vår konstruktorfunktion vi definierar greeting() varje gång, vilket inte är idealiskt. För att undvika detta kan vi definiera funktioner på prototypen istället, som vi kommer att titta på senare.

Färdigtställ vår konstruktör

Exemplet vi tittade på ovan var bara ett enkelt exempel för att komma igång. Låt oss nu gå vidare och skapa vår sista person() konstruktorfunktion.

  1. Ta bort koden du lagt in hittills, och lägg till denna konstruktör istället - den är exakt densamma som det enkla exempelet i princip, med lite mer komplexitet:
    function Person(first, last, age, gender, interests) {
      this.name = {
        first,
        last
      };
      this.age = age;
      this.gender = gender;
      this.interests = interests;
      this.bio = function() {
        alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
      };
      this.greeting = function() {
        alert('Hi! I\'m ' + this.name.first + '.');
      };
    };
  2. För att skapa ett objekt instans, lägg in följande rad:
    var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);

You'll now see that you can access the properties and methods just like we did with the first object we defined:

person1['age']
person1.interests[1]
person1.bio()
// etc.

Obs: Om du har problem med att få detta att fungera, försök jämföra koden mot vår version— se oojs-class-finished.html (live).

Further exercises

To start with, try adding a couple more object creation lines of your own, and try getting and setting the members of the resulting object instances.

In addition, there are a couple of problems with our bio() method — the output always includes the pronoun "He", even if your person is female, or some other preferred gender classification. And the bio will only include two interests, even if more are listed in the interests array. Can you work out how to fix this in the class definition (constructor)? You can put any code you like inside a constructor (you'll probably need a few conditionals and a loop). Think about how the sentences should be structured differently depending on gender, and depending on whether the number of listed interests is 1, 2, or more than 2.

Note: If you get stuck, we have provided an answer inside our GitHub repo (see it live) — try writing it yourself first though!

Andra sätt att skapa objektinstanser

Hittills har vi sett två olika sätt att skapa en objekt-instans — declaring an object literal, och med hjälp av en konstruktorfunktion (se ovan).

Dessa är korrekta, men det finns andra sätt - vi vill göra dig förtrogen med dessa om du stöter på dem i dina resor runt webben.

Object() Konstruktorn

Först av allt, kan du använda Object() konstruktorn för att skapa nya objekt . Ja, även generiska objekt har en konstruktör, som genererar ett tomt objekt.

  1. Försök att skriva in detta i din webbläsares JavaScript-konsol:
    var person1 = new Object();
  2. Detta lagrar ett tomt objekt i person1 variabeln. Du kan sedan lägga till egenskaper och metoder till detta objekt med hjälp av dot eller konsolnotation såsom önskas; prova dessa exempel:
    person1.name = 'Chris';
    person1['age'] = 38;
    person1.greeting = function() {
      alert('Hi! I\'m ' + this.name + '.');
    };
  3. Du kan också skicka en objektlitteral till Object() konstruktören som en paramete, för att på förhand fylla den med egenskaper/metoder. Prova detta:
    var person1 = new Object({
      name: 'Chris',
      age: 38,
      greeting: function() {
        alert('Hi! I\'m ' + this.name + '.');
      }
    });

Använda create() methoden

JavaScript har en inbyggd metod som kallas create(), som låter dig skapa en ny objekt-instans baserat på ett befintligt objekt.

  1. Prova detta i JavaScript-konsolen:
    var person2 = Object.create(person1);
  2. Proba nu dessa:
    person2.name
    person2.greeting()

Du ser att person2 har skapats baserat på person1 - det har samma egenskaper och metoder som finns tillgängliga för den. Detta är ganska användbart, eftersom det tillåter dig att skapa nya objektinstanser utan att behöva definiera en konstruktör.  Dessutom ger konstruktörer din kod mer ordning - du kan skapa dina konstruktörer på ett ställe, sedan skapa de instanser som behövs, på så sätt är det tydligt var de kommer ifrån.

Nackdelen är att create()stöds inte av IE8. Så konstruktörer kanske inte är rätt väg att gå om du vill stödja äldre webbläsare, eller om du behöver bara ett par kopior av ett objekt. Det är upp till dig vad du föredrar. Vissa tycker helt enkelt att create() är enklare att förstå och använda.

Vi kommer att undersöka effekterna av create() i mer detalj senare.

Sammanfattning

Denna artikel har gett en förenklad bild av objektorienterad teori - detta är inte hela historien, men det ger dig en uppfattning om vad vi har att göra med här. Dessutom har vi börjat titta på hur JavaScript relaterar och hur det skiljer sig från "klassiska OOP". Samt hur man skapar klasser i JavaScript med hjälp av konstruktorfunktioner och olika sätt att generera objektinstanser .

I nästa artikel kommer vi att undersöka JavaScript Object prototyper.

Dokumenttaggar och bidragare

 Bidragare till denna sida: DevelDoe
 Senast uppdaterad av: DevelDoe,