OOJS: Objektově orientovaný JavaVýukový program skriptu s příkladem

⚡ Chytré shrnutí

Objektově orientovaný JavaSkript modeluje entity reálného světa jako objekty, které nesou vlastnosti a metody. Tato stránka vysvětluje objektové literály, konstruktorové funkce, prototypy, třídy ES6, dědičnost a privátní pole s pomocí spustitelných příkladů, které můžete spustit a ověřit.

  • 🧱 Objekty: Objekt sdružuje související vlastnosti a metody, takže jedna proměnná může modelovat studenta, účet nebo domov.
  • 🏗️ Konstruktéři: Konstruktorová funkce s tento vytváří mnoho instancí z jednoho opakovaně použitelného plánu.
  • 🔁 Výčet: Smyčka for/in prochází každou vyčíslitelnou vlastností a vypisuje klíče a hodnoty bez pevně zakódovaných názvů.
  • ???? Třídy ES6: Klíčové slovo třídy je syntaktický cukr; metody stále existují na sdíleném objektu prototypu.
  • 🧬 Dědictví: automaticky rozšiřuje prototypy odkazů a super volá nadřazený konstruktor nebo přepsanou metodu.
  • 🔒 Zapouzdření: Pole s předponou # zůstávají soukromá, skrytá před Object.keys a JSON.stringify.
  • ⚙️ Praxe: Každý příklad na této stránce ukazuje ověřený výstup, takže můžete výsledky porovnávat během učení.

Objektově orientovaný JavaKoncepty skriptů (OOJS) s objekty, konstruktory a třídami

V čem je koncept OOPS JavaSkript?

Proměnné nebo pole často nestačí k simulaci reálných situací. JavaSkript umožňuje vytvářet objekty, které se chovají jako objekty ze skutečného života. Student nebo dům může být objekt s mnoha jedinečnými vlastnostmi. Pro usnadnění programování můžete na svých objektech vytvářet vlastnosti a metody. Pokud je vaším objektem student, bude mít vlastnosti jako křestní jméno, příjmení a ID a metody jako calculateRank nebo changeAddress. Pokud je vaším objektem dům, bude mít vlastnosti jako počet pokojů, barvu a umístění a metody jako calculateArea nebo changeOwner.

Objektově orientované programování v JavaScénář se tedy opírá o čtyři myšlenky, se kterými se na této stránce setkáte: skupinaping stav a chování do objektu, opětovné použití plánu prostřednictvím konstruktoru, sdílení metod prostřednictvím prototypu a omezení přímého přístupu k interním datům. Pokud s tímto jazykem začínáte, začněte s tímto úvod do JavaScénář a pak se sem vraťte.

Jak vytvořit objekt

Můžete vytvořit objekt takto:

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

NEBO s použitím kratšího tvaru objektového literálu:

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

Přístup k vlastnostem a metodám objektu

K vlastnosti objektu můžete přistupovat pomocí tečkové notace a metodu můžete volat přidáním závorek:

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

Zkuste tento příklad sami:

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

Výstup:

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

💡 Tip: Výše uvedený příklad používá dokument.napsat protože běží uvnitř editoru na této stránce. V reálných projektech dává přednost konzole.log pro ladění nebo DOM metody, jako například textObsah, Protože dokument.napsat Vymaže stránku, když je volána po dokončení načítání.

OOPS konstruktor

Vytváření objektů jeden po druhém není tak užitečné, protože byste museli opakovat stejný kód pro každého studenta. Zde přichází na řadu konstruktor objektů. Konstruktor je běžná funkce, která se volá s nový klíčové slovo; definuje typ objektu, který lze znovu použít pro každou jednotlivou instanci.

Uvnitř konstruktoru, tento odkazuje na nově sestavovaný objekt, takže každá instance obdrží svou vlastní kopii předaných hodnot. Související hodnoty, jako například značky, jsou často uloženy v řada aby je bylo možné sečíst v jednom průchodu.

Zkuste tento příklad sami:

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

Výstup:

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

Procházet vlastnosti objektu

Syntaxe:

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

Pro/v smyčka se obvykle používá k procházení vlastností objektu. Můžete mu dát libovolný název. proměnlivý, ale název objektu se musí shodovat s objektem, který již existuje. Při každém průchodu proměnná obsahuje vlastnost klíč jako řetězec, takže hodnota se čte s notací v hranatých závorkách, například zaměstnanec[x].

Zkuste tento příklad sami:

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

Výstup:

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

Je třeba si uvědomit dva body. Cyklus for/in také navštěvuje vyčíslitelné vlastnosti zděděné prostřednictvím řetězce prototypů, takže ochranný prvek, jako například Objekt.prototyp.hasOwnProperty.call(zaměstnanec, x) se často přidává. U objektů s prostým datem se Object.keys(zaměstnanec) or Object.entries(zaměstnanec) je obvykle přehlednější, protože oba vracejí pouze vlastnosti objektu.

Jaká je syntaxe třídy ES6 v JavaSkript?

ECMAScript 2015, běžně nazývaný ES6, přidal třída klíčové slovo. Třída je syntaktický cukr nad prototypovým systémem, který výše uvedená konstruktorová funkce již používá: nebyl zaveden žádný nový objektový model. Spuštění typ studenta na třídě stále vrací řetězec „function“ a každá metoda napsaná v těle třídy je nainstalována na Student.prototype, což znamená, že všechny instance sdílejí jednu kopii dané metody, místo aby každý objekt nesl svou vlastní.

Syntaxe také odstraňuje některé nedostatky. Těla tříd se vždy provádějí v striktním režimu a volají třídu bez nový vyvolá TypeError místo tichého znečištění globálního objektu a gettery, settery a statické členy mají vyhrazené místo pro uložení. Výsledkem je kratší kód, který vyjadřuje stejný záměr.

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

Výstup:

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

Poslední dva řádky to dokazují: třída je stále funkcí a metoda na instanci je tentýž funkční objekt uložený na prototypu.

Konstruktorová funkce vs. třída ES6

Vzhled Funkce konstruktoru Třída ES6
Prohlášení funkce Student(…) { } třída Student { konstruktor(…) { } }
Umístění metody Přiřazeno uvnitř funkce, takže každá instance dostane svou vlastní kopii, pokud nezapíšete do Student.prototype Zapsáno v těle třídy a automaticky umístěno na prototyp
Volání bez nového Běží tiše a tento je nedefinovaný nebo globální objekt Okamžitě vyvolá chybu TypeError.
Zvedání Deklarace funkcí jsou zvednuty a použitelné před definicí. V časové mrtvé zóně do vyhodnocení
Přísný režim Sleduje okolní scénář Vždy přísný
Dědictví Manuální: Object.create plus volání rodiči rozšiřuje a skvělý
Soukromé údaje Uzávěry nebo konvence pojmenování, jako například _váhy Skutečně soukromá pole s #
Podkladový model Prototypy Prototypy (identické za běhu)

Jak implementovat dědičnost pomocí extends a super

Dědičnost umožňuje specializovanému typu znovu použít vlastnosti a metody obecnějšího typu. Před ES6 to znamenalo ruční propojení řetězce prototypů ve třech samostatných krocích a bylo snadné na jeden z nich zapomenout.

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

Výstup:

I am Kevin White
true

Jedno rozšiřuje klíčové slovo provede všechny tři kroky za vás a skvělý poskytuje čistý způsob, jak dosáhnout nadřazeného objektu. Existují dvě různá využití skvělý:

  • super(…) jako hovor spustí nadřazený konstruktor. Je platný pouze uvnitř odvozeného konstruktoru a musí být spuštěn před dotykem. tento, jinak je vyvolána chyba ReferenceError.
  • super.method() protože vyhledávání vlastnosti volá nadřazenou verzi metody, kterou podřízená metoda přepsala, což je způsob, jakým rozšiřujete chování, místo abyste ho nahrazovali.
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);

Výstup:

I am Hannah Turner, roll number 23
true true
true

Třetí řádek je důležitý. Potvrzuje, že rozšiřuje vytvořil přesně ten prototyp, který odkazoval na manuální verzi sestavenou ručně, takže třídy nenahradily řetězení prototypů. Jednoduše skryly standard. Když je vlastnost načtena z st, engine se podívá na instanci a poté Student.prototype, pak Person.prototype, pak Objekt.prototypea zastaví se na první shodě; tato vyhledávací cesta je řetězec prototypů.

Warning️ Varování: Nikdy nepřiřazovat Student.prototype = Person.prototypeDíky tomu oba typy sdílejí jeden objekt, takže jakákoli metoda, kterou přidáte k podřízenému objektu, se přidá také k nadřazenému objektu. Použijte Objekt.vytvořit(Osoba.prototyp), nebo jednoduše použijte rozšiřuje.

Jak dosáhnout zapouzdření pomocí soukromých polí třídy

Zapouzdření znamená uchovatping vnitřní stav mimo dosah, takže se může změnit pouze metodami, které ovládáte. Po léta JavaVývojáři skriptů to zfalšovali úvodním podtržítkem, ale název jako _váhy je to pouze konvence a jakýkoli kód ji stále může přepsat. Moderní JavaSkript nabízí skutečné soukromí: pole, jehož název začíná na # je přístupný pouze uvnitř těla třídy, která jej deklaruje.

Soukromá pole přinášejí tři konkrétní výhody:

  • Před použitím musí být deklarovány v těle třídy, což na jednom místě dokumentuje vnitřní stav typu.
  • Jsou pro ně neviditelní Objektové klíče, JSON.stringifya for/in, aby se vnitřní stav nepřenášel do serializovaného výstupu.
  • Dotyk do soukromého pole zvenčí třídy je syntaktická chyba zachycená ještě před spuštěním kódu, nikoli tichá chyba.
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));

Výstup:

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

Zůstatek se nikdy neobjeví Objektové klíče nebo v řetězci JSON a negativní vklad je metodou odmítnut namísto poškození pole. získat zůstatek() accessor zpřístupňuje zobrazení pouze pro čtení, což je obvyklý způsob, jak bezpečně publikovat soukromý stav.

Nyní, když objekty, prototypy, třídy, dědičnost a zapouzdření dávají smysl, pokračujte ve vytváření. Procvičte si základy s těmito... praktický JavaPříklady skriptového kódu, propracovat se interaktivní JavaCvičení se skripty, aplikovat třídy na algoritmy, jako například rychlé řazení v JavaScénář, uklidit výstup pomocí JavaFormátování řetězce skriptua podívejte se, jak statické typing změny designu objektu v TypeScript.

Nejčastější dotazy

Vytvoří prázdný objekt, propojí ho s prototypem konstruktoru, spustí konstruktor s proměnnou „this“ vázanou na tento objekt a vrátí jej. Pokud konstruktor explicitně vrátí objekt, vrátí se místo toho tato hodnota.

Statickou metodu použijte, když logika patří k danému typu, nikoli k jedné instanci, například u továrny, která sestavuje objekt z JSON, nebo u pomocné metody, která porovnává dvě instance. Statické členy se volají u samotné třídy.

Protože „toto“ je určeno tím, jak je metoda volána, ne tím, kde je zapsána. Předání metody jako callback ztrácí příjemce. Opravte to navázáním metody v konstruktoru nebo její deklarací jako pole třídy s funkcí typu šipka.

Ne. Deklarací dvou metod se stejným názvem se zachová pouze ta poslední. Simulujte přetížení kontrolou arguments.length, použitím výchozích hodnot parametrů nebo přijetím jednoho objektu options s pojmenovanými vlastnostmi.

Ano. Asistenti kódování s umělou inteligencí zvládají tento refaktoring dobře, protože mapaping je mechanické. Vždy si zkontrolujte výsledek, protože asistenti mohou přehlédnout metody připojené k prototypu mimo konstruktor nebo přerušit volání nadřazeného konstruktoru.

Ano. Vygenerovaný kód je stále nutné číst, kontrolovat a ladit. Znalost chování prototypů, polí „this“ a privátních polí vám umožní odhalit nesprávný návrh dříve, než se dostane do produkčního prostředí.

Shrňte tento příspěvek takto: