Jak fungují prototypy JavaScriptu?

Prototypy v JavaScriptu jsou speciální téma. Pravděpodobně je nepoužijete protože třídy a některé rámce vás před tím chrání. Stále je však důležité vědět, jak fungují, je to základní součást jazyka. Znalost toho, jak fungují prototypy, vám také pomůže vypořádat se s podivnými chybami v těchto knihovnách nebo třídách.

V JavaScriptu můžete použít objekty jako „návrhy“ k vytváření nových objektů, a to dělá z objektu „návrh“ prototyp.

Když vytvoříte objekt s prototypem, nový objekt zdědí všechny vlastnosti a metody ze svého prototypu. Podívejme se na příklad:


// Let's create a regular object that
// we'll use as a prototype later
const dogProto = {
    eat: function() {
        console.log("This dog is eating");
    },
    bark: function() {
        console.log("This dog is barking");
    }
};

// Creating a new object using the prototype
const maxTheDog = Object.create(dogProto);

// `maxTheDog` has all the methods from its
// prototype, the `dogProto` object

maxTheDog.eat(); // Prints "This dog is eating"
maxTheDog.bark(); // Prints "This dog is barking"

V předchozích odstavcích jsem řekl, že objekty dědí vlastnosti a metody ze svého prototypu, ale „dědit“ není to pravé slovo. Programování založené na prototypech používá techniku ​​zvanou delegování .

Delegování funguje takto:když čtete vlastnost objektu nebo voláte metodu (např. maxTheDog.eat() ), stroj JavaScript nejprve hledá tuto vlastnost nebo metodu v samotném objektu. Pokud jej motor nenajde, vyhledá jej v prototypu.

Prototypy samotné mohou mít také prototypy. Pokud tedy engine JS nemohl najít vlastnost nebo metodu v prototypu, bude hledání pokračovat v prototypu prototypu. A v prototypu prototypu prototypu. A v prototypu prototypu je... no, máte nápad! 😉

Hledání bude pokračovat v řetězci prototypů, dokud nenajde vlastnost/metodu, nebo dokud nebude kde hledat.

Podívejme se na další příklad:

// Creating a new object using the prototype
const maxTheDog = Object.create(dogProto);

// Creating a new method in `maxTheDog`
maxTheDog.sleep = function() {
    console.log("This dog is sleeping");
};

maxTheDog.sleep(); // Prints "This dog is eating"
maxTheDog.bark(); // Prints "This dog is barking"

Když jsme zavolali maxTheDog.sleep() , modul JS jej našel v maxTheDog samotný objekt. Ale když jsme zavolali maxTheDog.bark() , motor to v objektu sám nenašel, není tam. Ale objekt má prototyp a engine tam našel metodu.

Pokud provedete změny v prototypu, ovlivní to také všechny objekty vytvořené z něj. Například:

// Let's add a new method to the prototype
// we created before
dogProto.howl = function() {
    console.log("This dog is howling!");
};

// Now, the `maxTheDog` object can howl too
maxTheDog.howl(); // Prints "This dog is howling!"

Funkce konstruktoru

Ve všech předchozích příkladech jsme použili Object.create metoda k vytvoření objektu pomocí prototypů. Není to však nejběžnější způsob, jak to udělat.

Objekty se obecně vytvářejí pomocí funkce konstruktoru. Funkce konstruktoru je běžná funkce, speciální jsou pouze dvě věci.

První je, že vytvoříte objekt voláním funkce s new klíčové slovo. A druhá je, že uvnitř funkce můžete použít this klíčové slovo, které je odkazem na vytvářený objekt.

// Constructor function
function Cat(name) {
    this.name = name;
}
// Let's create a new object using the constructor
const tomTheCat = new Cat("Tom");
console.log(tomTheCat.name); // Prints "Tom"

Ale kde je ten prototyp? Je to ve funkci konstruktoru. Funkce v JavaScriptu jsou objekty a mají prototype vlastnictví. Pokud použijete funkci jako konstruktor, tato vlastnost bude prototypem objektu, který vytvoříte.

Takže v příkladu prototyp tomTheCat je Cat.prototype . Můžeme to vidět na příkladu:když přidáme novou metodu do Cat.prototype , bude tato metoda dostupná také v tomTheCat objekt:

Cat.prototype.sayMeow = function() {
    // the "this" property refers to the object itself
    console.log(this.name + " says Meow!");
}
tomTheCat.sayMeow(); // Prints "Tom says Meow!"

Třídy jako syntaktický cukr

Před několika lety byly do JavaScriptu přidány třídy. Je důležité vědět, že třídy stále používají prototypy pod kapotou. Ve skutečnosti jsou třídy speciálním druhem funkcí a mají prototype majetek také.

Třída JavaScriptu je v podstatě „syntaktický cukr“. To znamená, že se jedná o prototypy se syntaxí, která se snadněji používá pro vývojáře z jiných programovacích jazyků.

Podívejte se na můj JavaScript Newsletter. Každé druhé pondělí jednoduché a praktické kroky k vylepšení vašich dovedností v JavaScriptu. Zaregistrujte se na https://nicozerpa.com/newsletter