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.

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.
