OOJS: Orientato agli oggetti JavaTutorial di scripting con esempio

⚡ Riepilogo intelligente

Orientato agli oggetti JavaQuesto script modella le entità del mondo reale come oggetti che possiedono proprietà e metodi. Questa pagina illustra i letterali oggetto, le funzioni costruttore, i prototipi, le classi ES6, l'ereditarietà e i campi privati, con esempi eseguibili che è possibile verificare.

  • 🧱 Oggetti: Un oggetto raggruppa proprietà e metodi correlati, in modo che una singola variabile possa modellare uno studente, un account o un'abitazione.
  • ???? ️ Costruttori: Una funzione costruttrice con questo Crea numerose istanze a partire da un singolo progetto riutilizzabile.
  • 🔁 Enumerazione: Il ciclo for/in scorre ogni proprietà enumerabile, stampando chiavi e valori senza inserire nomi fissi nel codice.
  • 📦 Classi ES6: La parola chiave `class` è zucchero sintattico; i metodi risiedono ancora nell'oggetto prototipo condiviso.
  • 🧬 Eredità: estende automaticamente i prototipi dei collegamenti e chiama il costruttore della classe padre o un metodo sovrascritto.
  • 🔒 incapsulamento: I campi con prefisso # rimangono privati ​​e nascosti da Object.keys e JSON.stringify.
  • ⚙️ Pratica: Ogni esempio in questa pagina mostra un output verificato, in modo da poter confrontare i risultati durante l'apprendimento.

Orientato agli oggetti JavaConcetti di programmazione orientata agli oggetti (OOJS) con oggetti, costruttori e classi.

In cosa consiste il concetto OOPS JavaCopione?

Molte volte le variabili o gli array non sono sufficienti per simulare situazioni di vita reale. JavaScript permette di creare oggetti che si comportano come oggetti reali. Uno studente o una casa possono essere oggetti con molte caratteristiche uniche. È possibile creare proprietà e metodi per i propri oggetti per semplificare la programmazione. Se l'oggetto è uno studente, avrà proprietà come nome, cognome e ID, oltre a metodi come calcolaClassifica o cambiaIndirizzo. Se l'oggetto è una casa, avrà proprietà come numero di stanze, colore delle pareti e posizione, oltre a metodi come calcolaArea o cambiaProprietario.

Programmazione orientata agli oggetti in JavaLa sceneggiatura si basa quindi su quattro idee che incontrerete in questa pagina: gruppoping stato e comportamento in un oggetto, riutilizzando un blueprint tramite un costruttore, condividendo i metodi tramite il prototipo e limitando l'accesso diretto ai dati interni. Se sei nuovo al linguaggio, inizia da questo introduzione a JavaCopione e poi tornare qui.

Come creare un oggetto

Puoi creare un oggetto come questo:

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

OPPURE, utilizzando la forma letterale dell'oggetto più breve:

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

Accedere alle proprietà e ai metodi dell'oggetto

È possibile accedere a una proprietà di un oggetto utilizzando la notazione con il punto, e si può chiamare un metodo aggiungendo le parentesi:

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

Prova tu stesso questo esempio:

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

Produzione:

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

Suggerimento: L'esempio sopra utilizza document.write perché viene eseguito all'interno dell'editor su questa pagina. Nei progetti reali, preferire console.log per il debug o metodi DOM come testoContenuto, perché document.write cancella la pagina quando viene richiamata dopo che il caricamento è terminato.

Costruttore OOPS

Creare oggetti uno alla volta non è molto utile, perché dovresti ripetere lo stesso codice per ogni studente. È qui che entra in gioco il costruttore di oggetti. Un costruttore è una funzione ordinaria che viene chiamata con il new parola chiave; definisce un tipo di oggetto che può essere riutilizzato per ogni singola istanza.

All'interno di un costruttore, questo si riferisce al nuovo oggetto in fase di costruzione, quindi ogni istanza riceve la propria copia dei valori passati. I valori correlati, come i segni, sono spesso memorizzati in un schieramento in modo che possano essere sommati in un unico passaggio.

Prova tu stesso questo esempio:

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

Produzione:

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

Passa attraverso le proprietà di un oggetto

Sintassi:

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

Il per/in loop viene solitamente utilizzato per esaminare le proprietà di un oggetto. Puoi dare un nome qualsiasi all'oggetto. variabile, ma il nome dell'oggetto deve corrispondere a un oggetto che esiste già. Ad ogni passaggio, la variabile contiene la proprietà chiave come stringa, quindi il valore viene letto con la notazione tra parentesi quadre come dipendente[x].

Prova tu stesso questo esempio:

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

Produzione:

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

Due punti meritano di essere ricordati. Un ciclo for/in visita anche le proprietà enumerabili ereditate attraverso la catena di prototipi, quindi una guardia come Object.prototype.hasOwnProperty.call(employee, x) viene spesso aggiunto. Per gli oggetti dati semplici, Chiavi oggetto (dipendente) or Voci oggetto (dipendente) è solitamente più chiaro, perché entrambi restituiscono solo le proprietà proprie dell'oggetto.

Qual è la sintassi della classe ES6 in JavaCopione?

ECMAScript 2015, comunemente chiamato ES6, ha aggiunto il classe parola chiave. Una classe è zucchero sintattico sul sistema di prototipi che la funzione costruttore sopra utilizza già: non è stato introdotto alcun nuovo modello a oggetti. Esecuzione tipo di studente su una classe restituisce ancora la stringa "function" e ogni metodo scritto nel corpo della classe viene installato su Prototipo studentesco, il che significa che tutte le istanze condividono una copia di quel metodo anziché ogni oggetto averne una propria.

La sintassi elimina anche alcuni spigoli vivi. I corpi delle classi vengono sempre eseguiti in modalità rigorosa, chiamando una classe senza new genera un TypeError invece di inquinare silenziosamente l'oggetto globale, e i metodi getter, setter e i membri statici hanno un posto dedicato in cui risiedere. Il risultato è un codice più breve che esprime lo stesso intento.

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

Produzione:

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

Le ultime due righe lo dimostrano: la classe è ancora una funzione e il metodo sull'istanza è esattamente lo stesso oggetto funzione memorizzato nel prototipo.

Funzione costruttore vs Classe ES6

Aspetto Funzione costruttore Classe ES6
Dichiarazione funzione Studente(…) { } classe Studente { costruttore(…) { } }
Posizionamento del metodo Assegnato all'interno della funzione, quindi ogni istanza ottiene la propria copia a meno che non si scriva su Prototipo studentesco Scritto nel corpo della classe e posizionato automaticamente sul prototipo
Chiamare senza nuovo Funziona silenziosamente e questo non è definito o l'oggetto globale Genera immediatamente un TypeError
sollevamento Le dichiarazioni di funzione vengono sollevate e sono utilizzabili prima della definizione Nella zona morta temporale fino alla valutazione
Modalità rigorosa Segue la sceneggiatura circostante Sempre severo
Eredità Manuale: Oggetto crea più un chiamata al genitore si estende and grande
Dati privati Chiusure o una convenzione di denominazione come _bilancia Campi privati ​​veri con #
Modello sottostante prototipi Prototipi (identici in fase di esecuzione)

Come implementare l'ereditarietà utilizzando extends e super

L'ereditarietà permette a un tipo specializzato di riutilizzare le proprietà e i metodi di un tipo più generale. Prima di ES6, ciò significava dover costruire manualmente la catena di prototipi in tre passaggi separati, ed era facile dimenticarne uno.

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

Produzione:

I am Kevin White
true

Migliori si estende la parola chiave esegue tutti e tre i passaggi per te e grande offre un modo pulito per raggiungere il genitore. Ci sono due usi distinti di grande:

  • super(…) come chiamata esegue il costruttore del genitore. È valido solo all'interno di un costruttore derivato e deve essere eseguito prima di poterlo modificare. questoaltrimenti viene generato un ReferenceError.
  • super.metodo() La ricerca di proprietà richiama la versione padre di un metodo che il figlio ha sovrascritto, ed è così che si estende il comportamento invece di sostituirlo.
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);

Produzione:

I am Hannah Turner, roll number 23
true true
true

La terza riga è quella importante. Conferma che si estende ha prodotto esattamente il prototipo collega la versione manuale costruita a mano, quindi le classi non hanno sostituito il concatenamento dei prototipi. Hanno semplicemente nascosto il codice ripetitivo. Quando una proprietà viene letta da st, il motore esamina l'istanza, quindi Prototipo studentesco, poi Persona prototipo, poi Oggetto.prototipoe si ferma alla prima corrispondenza; questo percorso di ricerca è la catena prototipo.

⚠️ Attenzione: Non assegnare mai Studente.prototipo = Persona.prototipoCiò fa sì che entrambi i tipi condividano un oggetto, quindi qualsiasi metodo aggiunto al figlio viene aggiunto anche al genitore. Usa Object.create(Person.prototype), oppure semplicemente usa si estende.

Come ottenere l'incapsulamento con campi di classe privati

L'incapsulamento significa mantenerloping stato interno fuori dalla tua portata in modo che possa cambiare solo attraverso metodi che controlli. Per anni JavaGli sviluppatori di script lo hanno falsificato con un trattino basso iniziale, ma un nome come _bilancia è solo una convenzione e qualsiasi codice può comunque sovrascriverla. Moderno JavaLo script offre una vera privacy: un campo il cui nome inizia con # è accessibile solo all'interno del corpo della classe che lo dichiara.

I terreni privati ​​offrono tre vantaggi concreti:

  • Devono essere dichiarati nel corpo della classe prima dell'uso, che documenta lo stato interno del tipo in un unico punto.
  • Sono invisibili a Chiavi oggetto, JSON.stringifye for/in, in modo che lo stato interno non si riversi nell'output serializzato.
  • Accedere a un campo privato dall'esterno della classe è un errore di sintassi, rilevato prima ancora che il codice venga eseguito, anziché un bug silenzioso.
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));

Produzione:

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

Il saldo non appare mai in Chiavi oggetto o nella stringa JSON, e il deposito negativo viene rifiutato dal metodo invece di corrompere il campo. ottenere il saldo() Il metodo di accesso espone una vista di sola lettura, che è il modo usuale per pubblicare in modo sicuro lo stato privato.

Ora che oggetti, prototipi, classi, ereditarietà e incapsulamento hanno un senso, continuate a costruire. Esercitatevi sui fondamenti con questi pratico JavaEsempi di codice script, lavorare attraverso interattivo JavaEsercizi di sceneggiatura, applicare classi ad algoritmi come ordinamento rapido in JavaCopione, riordina l'output usando JavaFormattazione della stringa di scripte vedere come statico typing modifica la progettazione degli oggetti in TypeScript.

DOMANDE FREQUENTI

Crea un oggetto vuoto, lo collega al prototipo del costruttore, esegue il costruttore con "this" associato a quell'oggetto e lo restituisce. Se il costruttore restituisce esplicitamente un oggetto, viene restituito quel valore.

Utilizza un metodo statico quando la logica appartiene al tipo piuttosto che a una singola istanza, come ad esempio una factory che crea un oggetto da JSON o una funzione di supporto che confronta due istanze. I membri statici vengono richiamati sulla classe stessa.

Perché "questo" viene deciso da come viene chiamato un metodo, non da dove è scritto. Passare un metodo come callback fa perdere il ricevitore. Risolvete il problema associando il metodo nel costruttore o dichiarandolo come campo di classe con una funzione freccia.

No. Dichiarare due metodi con lo stesso nome mantiene solo l'ultimo. Simula l'overloading ispezionando arguments.length, utilizzando valori predefiniti per i parametri o accettando un singolo oggetto options con proprietà denominate.

Sì. Gli assistenti di programmazione IA gestiscono bene quel refactoring perché la mappaping è meccanico. Rivedi sempre il risultato, poiché gli assistenti possono non individuare i metodi associati al prototipo al di fuori del costruttore o omettere una chiamata al costruttore del genitore.

Sì. Il codice generato deve comunque essere letto, revisionato e sottoposto a debug. Conoscere il comportamento di prototipi, "this" e campi privati ​​è ciò che permette di individuare un suggerimento errato prima che raggiunga la produzione.

Riassumi questo post con: