OOJS: Orientat pe obiecte JavaTutorial Script cu Exemplu

⚡ Rezumat inteligent

Orientat spre obiect JavaScriptul modelează entități din lumea reală ca obiecte care poartă proprietăți și metode. Această pagină explică literalii obiectelor, funcțiile constructorului, prototipurile, clasele ES6, moștenirea și câmpurile private cu exemple rulabile pe care le puteți executa și verifica.

  • 🧱 Obiecte: Un obiect grupează proprietăți și metode corelate, astfel încât o variabilă poate modela un elev, un cont sau o locuință.
  • 🏗️ Constructori: O funcție constructor cu acest creează mai multe instanțe dintr-un singur plan reutilizabil.
  • 🔁 Enumerare: Bucla for/in parcurge fiecare proprietate enumerabilă, afișând chei și valori fără a codifica hardcoded nume.
  • 📦 Clasele ES6: Cuvântul cheie `class` este `sugar sintactic`; metodele încă există pe obiectul prototip partajat.
  • 🧬 Moştenire: extinde automat prototipurile de linkuri și apelează constructorul părinte sau o metodă suprascrisă.
  • 🔒 încapsularea: Câmpurile cu prefixul # rămân private, ascunse de Object.keys și JSON.stringify.
  • ⚙️ Practică: Fiecare exemplu de pe această pagină prezintă rezultate verificate, astfel încât să puteți compara rezultatele pe măsură ce învățați.

Orientat spre obiect JavaConcepte de script (OOJS) cu obiecte, constructori și clase

În ce este OOPS Concept JavaScenariul?

De multe ori, variabilele sau matricele nu sunt suficiente pentru a simula situații din viața reală. JavaScriptul vă permite să creați obiecte care se comportă ca obiecte din viața reală. Un student sau o casă poate fi un obiect care are multe caracteristici unice. Puteți crea proprietăți și metode pentru obiectele dvs. pentru a facilita programarea. Dacă obiectul dvs. este un student, acesta va avea proprietăți precum prenume, nume și ID, plus metode precum calculateRank sau changeAddress. Dacă obiectul dvs. este o casă, acesta va avea proprietăți precum numărul de camere, culoarea vopselei și locația, plus metode precum calculateArea sau changeOwner.

Programarea orientată pe obiecte în JavaPrin urmare, scenariul se bazează pe patru idei pe care le veți întâlni pe această pagină: grupareping stare și comportament într-un obiect, reutilizând un plan prin intermediul unui constructor, partajând metode prin prototip și restricționând accesul direct la datele interne. Dacă sunteți nou în limbaj, începeți cu acest lucru introducere in JavaScenariu și apoi întoarce-te aici.

Cum se creează un obiect

Puteți crea un obiect ca acesta:

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

SAU, folosind forma literală a obiectului mai scurtă:

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

Accesați proprietățile și metodele obiectului

Puteți accesa o proprietate a unui obiect cu notația punct și puteți apela o metodă adăugând paranteze:

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

Încercați singur acest exemplu:

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

ieșire:

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

💡 Sfat: Exemplul de mai sus folosește document.write deoarece rulează în editorul de pe această pagină. În proiectele reale, este de preferat consolă.log pentru depanare sau metode DOM, cum ar fi textContent, Deoarece document.write șterge pagina când este apelată după ce încărcarea s-a terminat.

OOPS Constructor

Crearea obiectelor unul câte unul nu este atât de utilă, deoarece ar trebui să repetați același cod pentru fiecare elev. Aici intervine constructorul de obiecte. Un constructor este o funcție obișnuită care este apelată cu nou cuvânt cheie; acesta definește un tip de obiect ce poate fi reutilizat pentru fiecare instanță individuală.

În interiorul unui constructor, acest se referă la noul obiect construit, astfel încât fiecare instanță primește propria copie a valorilor transmise. Valorile conexe, cum ar fi marcajele, sunt adesea stocate într-un mulțime astfel încât acestea să poată fi totalizate într-o singură trecere.

Încercați singur acest exemplu:

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

ieșire:

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

Buclă prin proprietățile unui obiect

Sintaxă:

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

Pentru/în buclă este de obicei folosit pentru a parcurge proprietățile unui obiect. Puteți da orice nume obiectului variabil, dar numele obiectului trebuie să corespundă unui obiect care există deja. La fiecare trecere, variabila deține proprietatea cheie ca șir de caractere, deci valoarea este citită cu notație între paranteze, cum ar fi angajat[x].

Încercați singur acest exemplu:

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

ieșire:

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

Două aspecte merită ținute minte. O buclă for/in vizitează și proprietăți enumerabile moștenite prin lanțul prototip, deci o gardă precum Obiect.prototip.hasOwnProperty.call(angajat, x) se adaugă adesea. Pentru obiectele de date simple, Object.keys(angajat) or Object.entries(angajat) este de obicei mai clară, deoarece ambele returnează doar proprietățile proprii ale obiectului.

Care este sintaxa clasei ES6 în JavaScenariul?

ECMAScript 2015, denumit în mod obișnuit ES6, a adăugat clasă cuvânt cheie. O clasă este un zahăr sintactic peste sistemul prototip pe care funcția constructor de mai sus îl folosește deja: nu a fost introdus niciun model de obiect nou. Rulează tip de student într-o clasă returnează în continuare șirul „funcție”, iar fiecare metodă scrisă în corpul clasei este instalată pe Prototip student, ceea ce înseamnă că toate instanțele partajează o copie a acelei metode în loc ca fiecare obiect să aibă propria copie.

Sintaxa elimină și unele aspecte neașteptate. Corpurile claselor se execută întotdeauna în mod strict, apelând o clasă fără nou aruncă o eroare TypeError în loc să polueze silențios obiectul global, iar getter-ele, setter-ele și membrii statici au un loc dedicat unde să se afle. Rezultatul este un cod mai scurt care exprimă aceeași intenție.

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

ieșire:

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

Ultimele două linii dovedesc acest lucru: clasa este tot o funcție, iar metoda din instanță este același obiect funcție stocat în prototip.

Funcția constructorului vs. clasa ES6

Aspect Funcția constructor Clasa ES6
Declarație funcția Student(…) { } clasa Student { constructor(…) { } }
Plasarea metodei Atribuit în cadrul funcției, astfel încât fiecare instanță primește propria copie, cu excepția cazului în care scrieți în Prototip student Scris în corpul clasei și plasat automat pe prototip
Apel fără nou Funcționează în tăcere și acest este nedefinit sau obiectul global Lansează imediat o eroare TypeError
Ridicat Declarațiile de funcții sunt afișate și utilizabile înainte de definiție În zona inactivă temporală până la evaluare
Modul strict Urmează scenariul înconjurător Întotdeauna strict
Moştenire Manual: Object.create plus un apel către părinte extinde și super
Date private Închideri sau o convenție de denumire, cum ar fi _echilibru Câmpuri private adevărate cu #
Modelul de bază Prototipurilor Prototipuri (identice la momentul execuției)

Cum se implementează moștenirea folosind extends și super

Moștenirea permite unui tip specializat să reutilizeze proprietățile și metodele unui tip mai general. Înainte de ES6, aceasta însemna cablarea manuală a lanțului de prototipuri în trei etape separate și era ușor să uiți de unul dintre ele.

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

ieșire:

I am Kevin White
true

extinde cuvântul cheie efectuează toți cei trei pași pentru dvs. și super oferă o modalitate clară de a ajunge la părinte. Există două utilizări distincte ale super:

  • super(…) ca apel rulează constructorul părinte. Este valid doar în interiorul unui constructor derivat și trebuie să ruleze înainte de a atinge acest, altfel se generează o eroare ReferenceError.
  • super.method() deoarece o căutare de proprietăți invocă versiunea părinte a unei metode pe care copilul a suprascris-o, ceea ce reprezintă modul în care extindeți comportamentul în loc să îl înlocuiți.
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);

ieșire:

I am Hannah Turner, roll number 23
true true
true

A treia linie este cea importantă. Confirmă că extinde a produs exact prototipul, link-ul fiind versiunea manuală construită, deci clasele nu au înlocuit înlănțuirea prototipurilor. Ele au ascuns pur și simplu șablonul standard. Când o proprietate este citită din st, motorul analizează instanța, apoi Prototip student, Apoi Persoană.prototip, Apoi Obiect.prototipși se oprește la prima potrivire; acea cale de căutare este lanțul prototip.

⚠️ Atenție: Nu atribui niciodată Student.prototype = Person.prototypeAceasta face ca ambele tipuri să partajeze un singur obiect, astfel încât orice metodă pe care o adăugați la copil este adăugată și la părinte. Folosiți Object.create(Person.prototype), sau pur și simplu utilizați extinde.

Cum se realizează încapsularea cu câmpuri de clasă private

Încapsularea înseamnă keeping stare internă inaccesibilă, astfel încât se poate schimba doar prin metode pe care le controlezi. Ani de zile JavaDezvoltatorii de scripturi au falsificat-o cu o subliniere la început, dar un nume precum _echilibru este doar o convenție și orice cod o poate suprascrie. Modern JavaScriptul oferă confidențialitate reală: un câmp al cărui nume începe cu # este accesibilă doar în interiorul corpului clasei care o declară.

Domeniile private aduc trei beneficii concrete:

  • Acestea trebuie declarate în corpul clasei înainte de utilizare, ceea ce documentează starea internă a tipului într-un singur loc.
  • Sunt invizibili pentru Chei de obiect, JSON.stringifyși pentru/în, astfel încât starea internă să nu se scurgă în ieșirea serializată.
  • Atingerea unui câmp privat din afara clasei este o eroare de sintaxă, detectată înainte de rularea codului, mai degrabă decât o eroare silențioasă.
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));

ieșire:

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

Soldul nu apare niciodată în Chei de obiect sau în șirul JSON, iar depunerea negativă este respinsă de metodă în loc să corupă câmpul. obține echilibru() accesorul expune o vizualizare doar pentru citire, care este modalitatea obișnuită de a publica în siguranță starea privată.

Acum că obiectele, prototipurile, clasele, moștenirea și încapsularea au sens, continuă să construiești. Exersează elementele fundamentale cu acestea practic JavaExemple de cod de script, lucreaza prin interactiv JavaExerciții de scenariu, aplică clase algoritmilor precum sortare rapidă în JavaScenariu, ordonează ieșirea folosind JavaFormatarea șirurilor de scriptși vezi cât de statică esteping modifică designul obiectului în TypeScript.

Întrebări frecvente

Creează un obiect gol, îl leagă de prototipul constructorului, rulează constructorul cu „this” legat la acel obiect și îl returnează. Dacă constructorul returnează un obiect explicit, acea valoare este returnată în schimb.

Folosește o metodă statică atunci când logica aparține tipului respectiv și nu unei singure instanțe, cum ar fi o fabrică care construiește un obiect din JSON sau un helper care compară două instanțe. Membrii statici sunt apelați chiar în clasă.

Deoarece „aceasta” se decide prin modul în care este apelată o metodă, nu prin locul în care este scrisă. Transmiterea unei metode ca apel invers pierde receptorul. Remediați acest lucru prin legarea metodei în constructor sau prin declararea ei ca și câmp de clasă cu o funcție săgeată.

Nu. Declararea a două metode cu același nume păstrează doar ultima. Simulați supraîncărcarea prin inspectarea arguments.length, prin utilizarea valorilor implicite ale parametrilor sau prin acceptarea unui singur obiect de opțiuni cu proprietăți denumite.

Da. Asistenții de codare cu inteligență artificială gestionează bine această refactorizare, deoarece hartaping este mecanic. Revizuiți întotdeauna rezultatul, deoarece asistenții pot rata metode atașate prototipului în afara constructorului sau pot abandona un apel către constructorul părinte.

Da. Codul generat trebuie totuși citit, revizuit și depanat. Cunoașterea modului în care se comportă prototipurile, câmpurile „this” și câmpurile private vă permite să identificați o sugestie incorectă înainte ca aceasta să ajungă în producție.

Rezumați această postare cu: