OOJS: Olio-orientoitunut JavaSkriptiopas esimerkin kanssa

⚡ Älykäs yhteenveto

Kohdennettu JavaSkripti mallintaa reaalimaailman entiteettejä objekteina, joilla on ominaisuuksia ja metodeja. Tämä sivu selittää objektiliteraalit, konstruktorifunktiot, prototyypit, ES6-luokat, periytymisen ja yksityiset kentät suoritettavien ja tarkistettavien esimerkkien avulla.

  • 🧱 Objects: Objekti niputtaa toisiinsa liittyviä ominaisuuksia ja metodeja, joten yksi muuttuja voi mallintaa opiskelijaa, tiliä tai kotia.
  • 🏗️ Rakentajat: Rakentajafunktio, jossa on tätä luo useita instansseja yhdestä uudelleenkäytettävästä piirustuksesta.
  • 🔁 Luettelo: For/in-silmukka käy läpi jokaisen luetteloitavan ominaisuuden ja tulostaa avaimet ja arvot ilman kovakoodattuja nimiä.
  • 📦 ES6-luokat: Luokan avainsana on syntaktinen sokeri; metodit elävät edelleen jaetussa prototyyppiobjektissa.
  • 🧬 Perintö: laajentaa linkkien prototyyppejä automaattisesti ja super kutsuu pääkonstruktoria tai ohitettua metodia.
  • 🔒 kapselointi: #-etuliitteellä varustetut kentät pysyvät yksityisinä eli piilossa Object.keys- ja JSON.stringify-tiedostoilta.
  • ⚙️ Harjoitella: Jokainen tämän sivun esimerkki näyttää varmennettua tuotosta, joten voit vertailla tuloksia oppiessasi.

Kohdennettu JavaSkriptien (OOJS) käsitteet objekteine, konstruktoreineen ja luokkineen

Mitä OOPS-konsepti sisältää JavaKäsikirjoitus?

Usein muuttujat tai taulukot eivät riitä simuloimaan tosielämän tilanteita. JavaSkriptien avulla voit luoda objekteja, jotka toimivat kuin oikean elämän objektit. Opiskelija tai koti voi olla objekti, jolla on monia ainutlaatuisia ominaisuuksia. Voit luoda objekteille ominaisuuksia ja metodeja ohjelmoinnin helpottamiseksi. Jos objektisi on opiskelija, sillä on ominaisuuksia, kuten etunimi, sukunimi ja tunnus, sekä metodeja, kuten calculateRank tai changeAddress. Jos objektisi on koti, sillä on ominaisuuksia, kuten huoneiden lukumäärä, maalin väri ja sijainti, sekä metodeja, kuten calculateArea tai changeOwner.

Olio-ohjelmointi JavaKäsikirjoitus perustuu siis neljään ideaan, jotka kohtaat tällä sivulla: ryhmäping tilan ja käyttäytymisen lisääminen objektiin, piirustuksen uudelleenkäyttö konstruktorin kautta, metodien jakaminen prototyypin kautta ja sisäisen datan suoran käytön rajoittaminen. Jos olet uusi kielen käyttäjä, aloita tästä johdanto JavaKäsikirjoitus ja palaa sitten tänne.

Kuinka luoda objekti

Voit luoda objektin seuraavasti:

var objName = new Object();
objName.property1 = value1;
objName.property2 = value2;
objName.method1 = function()
{
  // line of code
}

TAI käyttämällä lyhyempää objektin literaalimuotoa:

var objName = { property1: value1, property2: value2, method1: function()
{
  // lines of code
} };

Käytä objektin ominaisuuksia ja menetelmiä

Voit käyttää objektin ominaisuutta pistemerkinnällä ja voit kutsua metodia lisäämällä sulkeita:

objectname.propertyname;   // read a property
objectname.methodname();   // call a method
objectname["propertyname"]; // bracket notation, useful for dynamic keys

Kokeile tätä esimerkkiä itse:

<html>
<head>
	<title>Objects!!!</title>
	<script type="text/javascript">
      var student = new Object();
      student.fName = "John";
      student.lName = "Smith";
      student.id = 5;
      student.markE = 76;
      student.markM = 99;
      student.markS = 87;
      student.calculateAverage = function()
      {
      	return (student.markE + student.markM + student.markS)/3;
      };
      student.displayDetails = function()
      {
        document.write("Student Id: " + student.id + "<br />");
        document.write("Name: " + student.fName + " " + student.lName + "<br />");
        var avg = student.calculateAverage();
        document.write("Average Marks: " + avg);
      };
		student.displayDetails();
	</script>
</head>
<body>
</body>
</html>

lähtö:

Student Id: 5
Name: John Smith
Average Marks: 87.33333333333333

💡 Vinkki: Yllä olevassa esimerkissä käytetään document.write koska se toimii tämän sivun editorin sisällä. Todellisissa projekteissa suositaan konsolin loki virheenkorjaukseen tai DOM-metodeihin, kuten tekstisisältö, Koska document.write tyhjentää sivun, kun sitä kutsutaan latauksen päätyttyä.

OOPS rakentaja

Objektien luominen yksi kerrallaan ei ole kovin hyödyllistä, koska tällöin joutuisit toistamaan saman koodin jokaiselle opiskelijalle. Tässä kohtaa objektikonstruktori tulee kuvaan. Konstruktori on tavallinen funktio, jota kutsutaan uusi avainsana; se määrittää objektityypin, jota voidaan käyttää uudelleen jokaisessa yksittäisessä instanssissa.

Rakentajan sisällä tätä viittaa uuteen rakennettavaan objektiin, joten jokainen instanssi saa oman kopionsa välitetyistä arvoista. Liittyvät arvot, kuten merkit, tallennetaan usein ryhmä jotta ne voidaan laskea yhteen yhdellä kertaa.

Kokeile tätä esimerkkiä itse:

<html>
<head>
	<script type="text/javascript">
		function Student(first, last, id, english, maths, science)
        {
          this.fName = first;
          this.lName = last;
          this.id = id;
          this.markE = english;
          this.markM = maths;
          this.markS = science;
          this.calculateAverage = function()
          {
         	 return (this.markE + this.markM + this.markS)/3;
          }
		  this.displayDetails = function()
		  {
            document.write("Student Id: " + this.id + "<br />");
            document.write("Name: " + this.fName + " " + this.lName + "<br />");
            var avg = this.calculateAverage();
            document.write("Average Marks: " + avg + "<br /><br />");
		  }
		}
        var st1 = new Student("John", "Smith", 15, 85, 79, 90);
        var st2 = new Student("Hannah", "Turner", 23, 75, 80, 82);
        var st3 = new Student("Kevin", "White", 4, 93, 89, 90);
        var st4 = new Student("Rose", "Taylor", 11, 55, 63, 45);
        st1.displayDetails();
        st2.displayDetails();
        st3.displayDetails();
        st4.displayDetails();
	</script>
</head>
<body>
</body>
</html>

lähtö:

Student Id: 15
Name: John Smith
Average Marks: 84.66666666666667

Student Id: 23
Name: Hannah Turner
Average Marks: 79

Student Id: 4
Name: Kevin White
Average Marks: 90.66666666666667

Student Id: 11
Name: Rose Taylor
Average Marks: 54.333333333333336

Kierrä objektin ominaisuuksien läpi

Syntaksi:

for (variablename in objectname)
{
  // lines of code to be executed
}

For/in silmukka käytetään yleensä objektin ominaisuuksien läpikäymiseen. Voit antaa sille minkä tahansa nimen. muuttuja, mutta objektin nimen on vastattava jo olemassa olevaa objektia. Jokaisella kierroksella muuttujalla on ominaisuus avain merkkijonona, joten arvo luetaan sulkeissa, kuten työntekijä[x].

Kokeile tätä esimerkkiä itse:

<html>
<head>
	<script type="text/javascript">
		var employee={first:"John", last:"Doe", department:"Accounts"};
        var details = "";
        document.write("<b>Using for/in loops </b><br />");
        for (var x in employee)
        {
          details = x + ": " + employee[x];
          document.write(details + "<br />");
        }
	</script>
</head>
<body>
</body>
</html>

lähtö:

Using for/in loops
first: John
last: Doe
department: Accounts

Kaksi asiaa on syytä muistaa. For/in-silmukka käy myös läpi prototyyppiketjun kautta periytyviä luetteloituja ominaisuuksia, joten suoja, kuten Object.prototype.hasOwnProperty.call(työntekijä, x) lisätään usein. Yksinkertaisille dataobjekteille Object.keys(työntekijä) or Object.entries(työntekijä) on yleensä selkeämpi, koska molemmat palauttavat vain objektin omat ominaisuudet.

Mikä on ES6-luokan syntaksi? JavaKäsikirjoitus?

ECMAScript 2015, jota kutsutaan yleisesti ES6:ksi, lisäsi luokka avainsana. Luokka on syntaktinen sokeri prototyyppijärjestelmän päälle, jota yllä oleva konstruktorifunktio jo käyttää: uutta oliomallia ei otettu käyttöön. Opiskelijatyyppi luokassa palauttaa edelleen merkkijonon ”function”, ja jokainen luokan runkoon kirjoitettu metodi asennetaan Opiskelija.prototyyppi, mikä tarkoittaa, että kaikki instanssit jakavat yhden kopion kyseisestä metodista sen sijaan, että jokainen objekti kantaisi omaa kopiotaan.

Syntaksi poistaa myös joitakin epätasaisuuksia. Luokan rungot suoritetaan aina tiukassa tilassa kutsuen luokkaa ilman uusi heittää TypeError-virheen sen sijaan, että se saastuttaisi hiljaisesti globaalin objektin, ja getter-, setter- ja staattisilla jäsenillä on oma paikkansa. Tuloksena on lyhyempää koodia, joka ilmaisee saman tarkoituksen.

class Student {
  constructor(first, last, id, english, maths, science) {
    this.fName = first;
    this.lName = last;
    this.id = id;
    this.marks = [english, maths, science];
  }

  calculateAverage() {
    const total = this.marks.reduce((sum, m) => sum + m, 0);
    return total / this.marks.length;
  }

  displayDetails() {
    console.log("Student Id: " + this.id);
    console.log("Name: " + this.fName + " " + this.lName);
    console.log("Average Marks: " + this.calculateAverage().toFixed(2));
  }
}

const st1 = new Student("John", "Smith", 15, 85, 79, 90);
st1.displayDetails();
console.log(typeof Student);
console.log(st1.calculateAverage === Student.prototype.calculateAverage);

lähtö:

Student Id: 15
Name: John Smith
Average Marks: 84.67
function
true

Kaksi viimeistä riviä todistavat asian: luokka on edelleen funktio, ja instanssin metodi on täsmälleen sama funktio-objekti, joka on tallennettu prototyyppiin.

Rakentajafunktio vs. ES6-luokka

Aspect Rakentajafunktio ES6-luokka
Ilmoitus funktio Opiskelija(…) { } luokka Opiskelija { konstruktori(…) { } }
Menetelmän sijoittelu Funktion sisällä määritetty, joten jokainen instanssi saa oman kopionsa, ellet kirjoita siihen Opiskelija.prototyyppi Kirjoitetaan luokan runkoon ja sijoitetaan prototyyppiin automaattisesti
Soitto ilman uutta Toimii äänettömästi ja tätä on määrittelemätön tai globaali objekti Heittää TypeError-virheen välittömästi
hoisting Funktiomäärittelyt nostetaan ja niitä voidaan käyttää ennen määritelmää Ajallisessa kuolleessa vyöhykkeessä, kunnes arvioidaan
Tiukka tila Noudattaa ympäröivää käsikirjoitusta Aina tiukka
Perintö Manuaalinen: Objekti.luo plus soittaa vanhemmalle ulottuu ja Super
Yksityiset tiedot Sulkemiset tai nimeämiskäytäntö, kuten _saldo Aidosti yksityiset kentät #
Taustalla oleva malli prototyypit Prototyypit (identtiset ajonaikana)

Perinnön toteuttaminen extends- ja super-komennoilla

Perintä antaa erikoistuneen tyypin käyttää uudelleen yleisemmän tyypin ominaisuuksia ja metodeja. Ennen ES6:ta tämä tarkoitti prototyyppiketjun kytkemistä käsin kolmessa erillisessä vaiheessa, ja yksi niistä oli helppo unohtaa.

function Person(fName, lName) {
  this.fName = fName;
  this.lName = lName;
}

Person.prototype.introduce = function () {
  return "I am " + this.fName + " " + this.lName;
};

function Student(fName, lName, id) {
  Person.call(this, fName, lName);   // 1. borrow the parent constructor
  this.id = id;
}

Student.prototype = Object.create(Person.prototype); // 2. link the chain
Student.prototype.constructor = Student;              // 3. repair constructor

var st = new Student("Kevin", "White", 4);
console.log(st.introduce());
console.log(st instanceof Person);

lähtö:

I am Kevin White
true

ulottuu avainsana suorittaa kaikki kolme vaihetta puolestasi, ja Super tarjoaa selkeän tavan tavoittaa vanhemman. Sanalla on kaksi erillistä käyttötarkoitusta. Super:

  • super(…) puheluna suorittaa pääkonstruktorin. Se on kelvollinen vain johdetun konstruktorin sisällä, ja se on suoritettava ennen kuin kosketat tätä, muuten heitetään ReferenceError-virhe.
  • super.metodi() ominaisuushakuna kutsuu metodin pääversiota, jonka lapsi on korvannut. Tällä tavoin metodin toimintaa laajennetaan sen korvaamisen sijaan.
class Person {
  constructor(fName, lName) {
    this.fName = fName;
    this.lName = lName;
  }

  introduce() {
    return "I am " + this.fName + " " + this.lName;
  }
}

class Student extends Person {
  constructor(fName, lName, id) {
    super(fName, lName);   // must run before "this" is used
    this.id = id;
  }

  introduce() {
    return super.introduce() + ", roll number " + this.id;
  }
}

const st = new Student("Hannah", "Turner", 23);
console.log(st.introduce());
console.log(st instanceof Student, st instanceof Person);
console.log(Object.getPrototypeOf(Student.prototype) === Person.prototype);

lähtö:

I am Hannah Turner, roll number 23
true true
true

Kolmas rivi on tärkein. Se vahvistaa, että ulottuu tuotti täsmälleen prototyyppilinkin manuaalisesti rakennetun version mukaisesti, joten luokat eivät korvanneet prototyyppien ketjutusta. Ne yksinkertaisesti piilottivat vakiomallin. Kun ominaisuus luetaan st, moottori tarkastelee instanssia ja sitten Opiskelija.prototyyppi, sitten Henkilö.prototyyppi, sitten Objekti.prototyyppi, ja pysähtyy ensimmäiseen osumaan; tämä hakupolku on prototyyppiketju.

⚠️ Varoitus: Älä koskaan määritä Opiskelija.prototyyppi = Henkilö.prototyyppiTämä tarkoittaa, että molemmilla tyypeillä on yksi yhteinen objekti, joten kaikki lapselle lisäämäsi metodit lisätään myös vanhempaan. Käytä Object.create(Henkilö.prototyyppi), tai käytä yksinkertaisesti ulottuu.

Kuinka saavuttaa kapselointi yksityisten luokkakenttien avulla

Kapselointi tarkoittaa säilytystäping sisäinen tila ulottumattomissasi, jotta se voi muuttua vain hallitsemillasi menetelmillä. Vuosien ajan JavaSkriptien kehittäjät väärensivät sen alaviivalla, mutta nimellä, kuten _saldo on vain käytäntö, ja mikä tahansa koodi voi silti korvata sen. Moderni JavaSkripti tarjoaa todellista yksityisyyttä: kenttä, jonka nimi alkaa # on käytettävissä vain sen luokan rungon sisällä, joka sen määrittelee.

Yksityisillä kentillä on kolme konkreettista hyötyä:

  • Ne täytyy deklaroida luokan rungossa ennen käyttöä, mikä dokumentoi tyypin sisäisen tilan yhdessä paikassa.
  • Ne ovat näkymättömiä Objektiavaimet, JSON.stringify, ja for/in, jotta sisäinen tila ei vuoda sarjamuotoiseen lähtöön.
  • Yksityisen kentän koskettaminen luokan ulkopuolelta on syntaksivirhe, joka havaitaan ennen koodin suorittamista, eikä hiljainen virhe.
class BankAccount {
  #balance = 0;

  constructor(owner, opening) {
    this.owner = owner;
    this.#balance = opening;
  }

  deposit(amount) {
    if (amount <= 0) {
      return "Deposit must be positive";
    }
    this.#balance += amount;
    return this.owner + " balance: " + this.#balance;
  }

  get balance() {
    return this.#balance;
  }
}

const acc = new BankAccount("John", 500);
console.log(acc.deposit(250));
console.log(acc.deposit(-40));
console.log("Read via getter: " + acc.balance);
console.log("Own keys: " + Object.keys(acc));
console.log("JSON: " + JSON.stringify(acc));

lähtö:

John balance: 750
Deposit must be positive
Read via getter: 750
Own keys: owner
JSON: {"owner":"John"}

Saldo ei koskaan näy Objektiavaimet tai JSON-merkkijonossa, ja metodi hylkää negatiivisen talletuksen kentän korruptoinnin sijaan. hae saldo() aksessori näyttää vain luku -näkymän, joka on tavanomainen tapa julkaista yksityinen tila turvallisesti.

Nyt kun oliot, prototyypit, luokat, periytyminen ja kapselointi ovat järkeviä, jatka rakentamista. Harjoittele perusteita näillä. käytännön JavaSkriptikoodiesimerkkejä, käydä läpi vuorovaikutteinen JavaKäsikirjoitusharjoituksia, soveltaa luokkia algoritmeihin, kuten pikalajittelu sisään JavaKäsikirjoitus, siisti tuloste käyttämällä JavaSkriptimerkkijonojen muotoilu, ja katso kuinka staattinen typing muuttaa objektin suunnittelua TypeScript.

UKK

Se luo tyhjän objektin, linkittää sen konstruktorin prototyyppiin, suorittaa konstruktorin "this"-sidoksella kyseiseen objektiin ja palauttaa sen. Jos konstruktori palauttaa objektin eksplisiittisesti, palautetaan sen arvo.

Käytä staattista metodia, kun logiikka kuuluu tyyppiin eikä yksittäiseen instanssiin, kuten esimerkiksi factory, joka rakentaa objektin JSON-kielestä, tai helper, joka vertaa kahta instanssia. Staattisia jäseniä kutsutaan itse luokasta.

Koska "tämä" määräytyy sen mukaan, miten metodia kutsutaan, ei sen kirjoituspaikan mukaan. Metodin välittäminen takaisinkutsuna menettää vastaanottajan. Korjaa ongelma sitomalla metodi konstruktorissa tai määrittämällä se luokkakenttänä nuolifunktiolla.

Ei. Kahden samannimisen metodin määrittäminen säilyttää vain viimeisen. Simuloi ylikuormitusta tutkimalla arguments.length-muuttujaa, käyttämällä oletusparametrien arvoja tai hyväksymällä yksittäinen asetusobjekti nimetyillä ominaisuuksilla.

Kyllä. Tekoälykoodauksen avustajat käsittelevät refaktoroinnin hyvin, koska karttaping on mekaaninen. Tarkista aina tulos, koska assistentit voivat unohtaa prototyyppiin liitetyt metodit konstruktorin ulkopuolella tai pudottaa kutsun pääkonstruktoriin.

Kyllä. Luotu koodi on edelleen luettava, tarkistettava ja debugattava. Prototyyppien, "tämän" ja yksityisten kenttien toiminnan tunteminen auttaa havaitsemaan virheelliset ehdotukset ennen kuin ne pääsevät tuotantoon.

Tiivistä tämä viesti seuraavasti: