OOJS: Objektno orijentirano JavaVodič za skriptu s primjerom

⚡ Pametni sažetak

Objektno orijentirano JavaSkripta modelira entitete iz stvarnog svijeta kao objekte koji nose svojstva i metode. Ova stranica objašnjava literale objekata, konstruktorske funkcije, prototipove, ES6 klase, nasljeđivanje i privatna polja s primjerima koje možete pokrenuti i provjeriti.

  • 🧱 objekti: Objekt objedinjuje povezana svojstva i metode tako da jedna varijabla može modelirati studenta, račun ili dom.
  • 🏗️ Konstruktori: Konstruktorska funkcija s to stvara mnogo instanci iz jednog višekratno upotrebljivog nacrta.
  • 🔁 Nabrajanje: Petlja for/in prolazi kroz svako nabrojivo svojstvo, ispisujući ključeve i vrijednosti bez fiksno kodiranih imena.
  • ???? ES6 klase: Ključna riječ klase je sintaktički šećer; metode se i dalje nalaze na zajedničkom objektu prototipa.
  • 🧬 nasljedstvo: automatski proširuje prototipove poveznica, a super poziva roditeljski konstruktor ili nadjačanu metodu.
  • 🔒 ovijanje: Polja s prefiksom # ostaju privatna, skrivena od Object.keys i JSON.stringify.
  • Praksa: Svaki primjer na ovoj stranici prikazuje provjereni izlaz, tako da možete uspoređivati ​​rezultate dok učite.

Objektno orijentirano JavaKoncepti skripte (OOJS) s objektima, konstruktorima i klasama

U čemu je OOPS koncept JavaSkripta?

Mnogo puta varijable ili nizovi nisu dovoljni za simulaciju situacija iz stvarnog života. JavaSkripta vam omogućuje stvaranje objekata koji se ponašaju poput stvarnih objekata. Student ili dom mogu biti objekti koji imaju mnogo jedinstvenih karakteristika. Možete stvoriti svojstva i metode na svojim objektima kako biste olakšali programiranje. Ako je vaš objekt student, imat će svojstva poput imena, prezimena i ID-a, plus metode poput calculateRank ili changeAddress. Ako je vaš objekt dom, imat će svojstva poput broja soba, boje i lokacije, plus metode poput calculateArea ili changeOwner.

Objektno orijentirano programiranje u JavaSkripta se stoga temelji na četiri ideje koje ćete susresti na ovoj stranici: grupaping stanje i ponašanje u objekt, ponovna upotreba nacrta putem konstruktora, dijeljenje metoda putem prototipa i ograničavanje izravnog pristupa internim podacima. Ako ste novi u jeziku, počnite s ovim uvod u JavaScript a onda se vrati ovamo.

Kako stvoriti objekt

Možete stvoriti objekt poput ovog:

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

ILI, korištenjem kraćeg oblika objektnog literala:

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

Pristup svojstvima i metodama objekta

Svojstvu objekta možete pristupiti pomoću točkaste notacije, a metodu možete pozvati dodavanjem zagrada:

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

Isprobajte sami ovaj primjer:

<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>

Izlaz:

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

💡 Savjet: Gornji primjer koristi dokument.pisanje jer se izvršava unutar editora na ovoj stranici. U stvarnim projektima, preferirajte konzola.log za otklanjanje pogrešaka ili DOM metode kao što su textContent, Jer je dokument.pisanje briše stranicu kada se pozove nakon što je učitavanje završeno.

OOPS konstruktor

Stvaranje objekata jednog po jednog nije toliko korisno, jer biste morali ponavljati isti kod za svakog učenika. Tu na scenu stupa konstruktor objekata. Konstruktor je obična funkcija koja se poziva s novi ključna riječ; definira tip objekta koji se može ponovno koristiti za svaku pojedinačnu instancu.

Unutar konstruktora, to odnosi se na novi objekt koji se gradi, tako da svaka instanca prima vlastitu kopiju proslijeđenih vrijednosti. Povezane vrijednosti poput oznaka često se pohranjuju u poredak tako da se mogu zbrojiti u jednom prolazu.

Isprobajte sami ovaj primjer:

<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>

Izlaz:

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

Prođite kroz svojstva objekta

Sintaksa:

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

Za/u petlja obično se koristi za pregled svojstava objekta. Možete mu dati bilo koje ime varijabla, ali naziv objekta mora odgovarati objektu koji već postoji. U svakom prolazu, varijabla sadrži svojstvo ključ kao niz znakova, pa se vrijednost čita s notacijom u zagradama kao što je zaposlenik[x].

Isprobajte sami ovaj primjer:

<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>

Izlaz:

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

Vrijedi zapamtiti dvije točke. Petlja for/in također posjećuje nabrojiva svojstva naslijeđena kroz lanac prototipova, pa stoga zaštitnik poput Objekt.prototip.hasOwnProperty.call(zaposlenik, x) često se dodaje. Za obične podatkovne objekte, Object.keys(zaposlenik) or Objekt.unosi(zaposlenik) obično je jasnije, jer oba vraćaju samo svojstva objekta.

Koja je sintaksa ES6 klase u JavaSkripta?

ECMAScript 2015, obično nazvan ES6, dodao je razred ključna riječ. Klasa je sintaktički šećer nad prototipnim sustavom koji gornja konstruktorska funkcija već koristi: nije uveden novi objektni model. Izvođenje vrsta učenika na klasi i dalje vraća niz znakova "function", a svaka metoda napisana u tijelu klase je instalirana na Student.prototip, što znači da sve instance dijele jednu kopiju te metode umjesto da svaki objekt nosi svoju vlastitu.

Sintaksa također uklanja neke grube rubove. Tijela klasa uvijek se izvršavaju u strogom načinu rada, pozivajući klasu bez novi baca TypeError umjesto da tiho zagađuje globalni objekt, a getteri, seteri i statički članovi imaju namjensko mjesto za život. Rezultat je kraći kod koji izražava istu namjeru.

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);

Izlaz:

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

Posljednja dva retka dokazuju poantu: klasa je i dalje funkcija, a metoda na instanci je isti onaj objekt funkcije pohranjen na prototipu.

Konstruktorska funkcija u odnosu na ES6 klasu

Aspekt Funkcija konstruktora ES6 klasa
izjava funkcija Student(…) { } klasa Student { konstruktor(…) { } }
Postavljanje metode Dodijeljeno unutar funkcije, tako da svaka instanca dobiva svoju kopiju osim ako ne pišete u Student.prototip Napisano u tijelu klase i automatski postavljeno na prototip
Poziv bez novog Radi tiho i to nije definiran ili je globalni objekt Odmah izbacuje TypeError
Dizanje Deklaracije funkcija se podižu i mogu se koristiti prije definicije. U vremenskoj mrtvoj zoni dok se ne procijeni
Strogi način rada Slijedi okolni scenarij Uvijek strog
Nasljeđivanje Priručnik: Object.create plus poziv roditelju proteže se i super
Privatni podaci Zatvaranja ili konvencija imenovanja kao što je _ravnoteža Prava privatna polja s #
Temeljni model prototipova Prototipovi (identični za vrijeme izvođenja)

Kako implementirati nasljeđivanje pomoću extends i super

Nasljeđivanje omogućuje specijaliziranom tipu ponovnu upotrebu svojstava i metoda općenitijeg tipa. Prije ES6, to je značilo ručno povezivanje lanca prototipa u tri odvojena koraka, a bilo je lako zaboraviti jedan od njih.

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);

Izlaz:

I am Kevin White
true

The proteže se ključna riječ izvršava sva tri koraka za vas i super pruža čist način dosezanja roditelja. Postoje dvije različite upotrebe super:

  • super(…) kao poziv pokreće roditeljski konstruktor. Valjan je samo unutar izvedenog konstruktora i mora se pokrenuti prije nego što dodirnete to, inače se izbacuje ReferenceError.
  • super.method() jer pretraga svojstva poziva roditeljsku verziju metode koju je podređena metoda nadjačala, što je način na koji proširujete ponašanje umjesto da ga zamjenjujete.
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);

Izlaz:

I am Hannah Turner, roll number 23
true true
true

Treći redak je važan. On potvrđuje da proteže se proizveo je točno onu vezu prototipa, ručna verzija izgrađena ručno, tako da klase nisu zamijenile ulančavanje prototipova. Jednostavno su sakrile predložak. Kada se svojstvo čita iz st, motor pregledava instancu, a zatim Student.prototip, A zatim Osoba.prototip, A zatim Objekt.prototip, i zaustavlja se na prvom podudaranju; taj put pretraživanja je lanac prototipa.

⚠️ Upozorenje: Nikad ne dodijeli Student.prototip = Osoba.prototipTo znači da oba tipa dijele jedan objekt, pa se svaka metoda koju dodate podređenom objektu dodaje i roditeljskom objektu. Koristite Objekt.kreiraj(Osoba.prototip)ili jednostavno koristite proteže se.

Kako postići enkapsulaciju s privatnim poljima klase

Enkapsulacija znači čuvanjeping unutarnje stanje izvan dohvata tako da se može promijeniti samo metodama koje kontrolirate. Godinama JavaProgrameri skripti su to lažirali s vodećom podcrtom, ali imenom poput _ravnoteža je samo konvencija i bilo koji kod je i dalje može prebrisati. Moderno JavaSkripta nudi pravu privatnost: polje čije ime počinje s # dostupan je samo unutar tijela klase koja ga deklarira.

Privatna polja donose tri konkretne prednosti:

  • Prije upotrebe moraju se deklarirati u tijelu klase, što na jednom mjestu dokumentira unutarnje stanje tipa.
  • Oni su nevidljivi za Objekt.ključevi, JSON.stringify, i for/in, tako da interno stanje ne procuri u serijalizirani izlaz.
  • Dodirivanje privatnog polja izvan klase je sintaktička greška, uočena prije nego što se kod uopće pokrene, a ne tiha greška.
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));

Izlaz:

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

Stanje se nikada ne pojavljuje u Objekt.ključevi ili u JSON nizu, a negativni depozit metoda odbacuje umjesto da ošteti polje. dohvati stanje() Pristupnik otkriva prikaz samo za čitanje, što je uobičajeni način sigurnog objavljivanja privatnog stanja.

Sada kada objekti, prototipovi, klase, nasljeđivanje i enkapsulacija imaju smisla, nastavite s izgradnjom. Vježbajte osnove s ovim. praktičan JavaPrimjeri skriptnog koda, proraditi interaktivan JavaVježbe sa skriptama, primijenite klase na algoritme kao što su brzo sortiranje u JavaScript, uredite izlaz pomoću JavaFormatiranje niza skriptei pogledajte kako statički typing mijenja dizajn objekta u TypeScript.

Pitanja i odgovori

Stvara prazan objekt, povezuje ga s prototipom konstruktora, pokreće konstruktor s "this" vezanim za taj objekt i vraća ga. Ako konstruktor eksplicitno vraća objekt, umjesto toga se vraća ta vrijednost.

Koristite statičku metodu kada logika pripada tipu, a ne jednoj instanci, kao što je tvornica koja gradi objekt iz JSON-a ili pomoćna metoda koja uspoređuje dvije instance. Statički članovi pozivaju se na samoj klasi.

Jer "ovo" određuje kako se metoda poziva, a ne gdje je napisana. Prosljeđivanje metode kao povratnog poziva gubi prijemnik. Ispravite to povezivanjem metode u konstruktoru ili deklariranjem kao polja klase sa strelicom.

Ne. Deklarisanjem dviju metoda s istim imenom zadržava se samo posljednja. Simulirajte preopterećenje pregledom arguments.length, korištenjem zadanih vrijednosti parametara ili prihvaćanjem jednog objekta opcija s imenovanim svojstvima.

Da. AI asistenti za kodiranje dobro se nose s tim refaktoriranjem jer mapaping je mehanički. Uvijek pregledajte rezultat, budući da asistenti mogu propustiti metode pridružene prototipu izvan konstruktora ili preusmjeriti poziv roditeljskom konstruktoru.

Da. Generirani kod i dalje treba pročitati, pregledati i otkloniti pogreške. Poznavanje ponašanja prototipova, "this" i privatnih polja omogućuje vam uočavanje netočnog prijedloga prije nego što dođe u produkciju.

Sažmite ovu objavu uz: