Co je prototyp v JavaScriptu?

Když jsem začal pracovat na projektu s Vue.js, došel jsem k poznání, že o JavaScriptu toho moc nevím. Od té doby jsem hledal JS, což mě pak přivedlo k objektově orientovanému programování v JavaScriptu. Dozvěděl jsem se o mnoha věcech, ale nejvíce jsem se potýkal s konceptem prototypů.

Doufám, že tímto blogovým příspěvkem to dokážu vysvětlit srozumitelným způsobem.

Malý úvod

Konstruktor je funkce, která vytváří nové objekty. V JavaScriptu to vypadá takto:

function Person(name, age) {
   this.name = name;
   this.age = age;
}

Syntaxe pro vytvoření nového objektu pomocí konstruktoru vypadá takto:

const me = new Person("Nicole", 19);

me nyní má name „Nicole“ a age 19. Snadné a jednoduché, jak byste očekávali.

Nyní si představte, že bychom chtěli vytvořit objekt Person s vlastnostmi paže, ruce, prsty a jméno:

function Person(arms, hands, fingers, name) {
   this.arms = arms;
   this.hands = hands;
   this.fingers = fingers;
   this.name = name;
}

Když vytvoříte čtyři instance Person , bude to vypadat takto:

const person1 = new Person(2, 2, 10, "Alice");
const person2 = new Person(2, 2, 10, "Bob");
const person3 = new Person(2, 2, 10, "Ursula");
const person4 = new Person(2, 2, 10, "Hanspeter");

Docela otravné a velmi se opakující... Tehdy se prototypy stanou užitečnými.

Prototypy

Prototypy se používají ke sdílení vlastností mezi všemi instancemi objektu. Vezměte si příklad shora:

Person.prototype = {
   constructor: Person,
   arms: 2,
   hands: 2,
   fingers: 10
}

Pomocí tohoto prototypového objektu vytvoříte čtyři instance Person s konstruktorem vypadá mnohem čistěji a je také méně práce:

function Person(name) {
   this.name = name;
}
const person1 = new Person("Alice");
const person2 = new Person("Bob");
const person3 = new Person("Ursula");
const person4 = new Person("Hanspeter");

Jak jsem řekl, mnohem menší a méně se opakující práce, ale všechny mají stejné vlastnosti jako ty vytvořené výše bez prototypu.

Nejen, že to vypadá čistěji, ale je snazší měnit hodnoty.

Řekněme, že jste – z nějakého opravdu hloupého důvodu – zadali 2 ruce pro každou osobu, ale program ve skutečnosti vytváří lidi pouze jednou rukou (proč bychom potřebovali vlastnosti paže a prsty, je teď zbytečné). Museli byste projít každým. svobodný . instance objektu a změnit nejen hodnotu 2 ruce, ale i 10 prstů. S pouhými čtyřmi instancemi byste museli provést osm změn. S prototypem budete muset vždy provést pouze dvě změny.

Není to nejlepší příklad, ale myslím, že to vystihuje podstatu věci.

Vlastnost jednoho prototypu vs objekt prototypu

Výše jsem použil prototyp objektu což je dobré, když by mělo být sdíleno mnoho vlastností. Pokud však existuje pouze jedna sdílená vlastnost, můžete ji zapsat takto:

Person.prototype.age = 30;

Není třeba ho dělat větší, než musí být.

Prototypové funkce

S prototypem je také možné uložit funkce jako vlastnosti.
Prototyp objektu:

Person.prototype = {
   introduce: function() {
      console.log(`Hello, my name is ${this.name}`);
   }
}

Vlastnost jednoho prototypu:

Person.prototype.introduce = function(){
   console.log(`Hello, my name is ${this.name}`);
}

konstruktor:osoba

Možná jste si všimli, že jsem definoval konstruktor v objektu prototypu. To je důležité, protože pokud nedefinujeme konstruktor, objekty budou mít Object jako jeho konstruktor a ne Person .

Dobře, teď tuto větu rozebereme, aby to bylo jasnější.

Máte konstruktor pro objekt.

function Person(name, age){
   this.name = name;
   this.age = age;
}

Poté pomocí tohoto konstruktoru vytvoříte objekt.

const me = new Person("Nicole", 19);

Konstruktor me je Person . Myslím, že mnohé je jasné.

me.constructor === Person
→ true

Když však vytvoříte prototypový objekt pro Person a nedefinujte konstruktor me bude mít konstruktor Object .

Person.prototype = {
   introduce: function() {
      console.log(`Hello, my name is ${this.name}`);
   }
}
const me = new Person("Nicole", 19);
console.log(me.constructor === Person);
console.log(me.constructor === Object);
→ false
  true

Ale proč?

Řetězec prototypů

Abychom vysvětlili prototypový řetězec, zaměřme se nejprve pouze na objekty. Když vytvoříte objekt, můžete zkontrolovat jeho vlastnosti pomocí hasOwnProperty .

Ale odkud to pochází? Nikdy jsme to nikde nedefinovali, přesto to můžeme použít. Odpověď je, že všechny objekty dědí od Object který má své vlastní prototypové vlastnosti. Můžete to zkontrolovat vytvořením jednoduchého objektu a kontrolou jeho konstruktoru.

let exampleObject = {
   something: "hi"
}
console.log(exampleObject.constructor === Object);
→ true

Všechny objekty tedy pocházejí z Object , může používat jeho vlastnosti prototypu a mít Object jako konstruktér. To dává smysl.

Nyní, když vytvoříte prototyp objektu , je to objekt, a proto dědí z Object . Proto musíte definovat konstruktor nebo jinak své instance Person bude mít konstruktor Object .

Object.prototype -zděděno-> Person.prototype ={} -zděděno-> me

Děkuji

Abych byl upřímný, nečekal jsem, že tento článek bude tak dlouhý (nevím, co se stalo), takže pokud jste se dostali až sem, vážně, děkuji za přečtení.