Właściwość prototype w JavaScript

Próbując podejść do tematu obiektowości w JavaScripcie musisz niejako zapomnieć o filozofii znanej z języków takich jak Java czy C# i zapoznać się z tematem na nowo. Oczywiście, wszelkie zasady programowania zorientowanego obiektowo występują także i tutaj, jednak forma prezentacji daleka jest od tego, do czego przyzwyczaiły nas inne języki. Tutaj jako bohater pierwszoplanowy jawi się właściwość prototype, budząca skrajne emocje wśród osób, które miały z nią do czynienia: jedni jej nienawidzą, inni uznają za wynaturzenie, a jeszcze inni kochają za to, że w ogóle istnieje.

 

Trochę teorii

W JavaScript wszystko to, co nie jest typem prymitywnym (undefined, null, boolean, number oraz string*) jest obiektem. Każdy obiekt posiada właściwość prototype, która również jest obiektem. Prototype pozwala rozszerzyć definicję klasy** o nowe metody oraz pola, także w predefiniowanych klasach, takich jak String, Date czy Array. W ten sposób JavaScript zyskuje mechanizmy, które z jednej strony pozwalają na tworzenie kodu obiektowego, a z drugiej – na rozbudowę kluczowych dla języka klas predefiniowanych.

 

* W JavaScript string występuje zarówno jako typ prymitywny (string literal) oraz jako obiekt (String object).

** Słowo „klasa” jest tu trochę naciągane. JavaScript nie posiada klas, a jedynie bazujący na prototype model dziedziczenia. Mimo to JavaScript jest określany jako zorientowany obiektowo (OOP) ze względu na istnienie dziedziczenia, enkapsulacji oraz polimorfizmu (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript).

 

Przykład 1: prototype dla obiektu typu String

String.prototype.startsWith = function (str) {
    return this.indexOf(str) === 0;
}
if ("prototype".startsWith("pro")) {
    document.write("Wyraz prototype zaczyna się od pro");
}

Wynik:

 

Przykład 2: prototype dla obiektu typu Array

Poniższy kod dodaje do obiektu Array metodę avg(), która zwraca średnią arytmetyczną elementów tej tablicy (przy założeniu, że elementy są liczbami).

function arrayGetAvg() {
    var sum = 0;
    var count = this.length;
    for (var i = 0; i < this.length; i++)
    {
        sum += this[i];
    }

    return (sum/count);
}
Array.prototype.avg = arrayGetAvg;
var myArray = new Array(1, 31, 53, 14, 45);
document.write(myArray.avg());

Wynik:

 

Więcej informacji

  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
  2. https://msdn.microsoft.com/en-us/library/f5s9ycex%28v=vs.94%29.aspx
  3. http://www.w3schools.com/js/js_object_prototypes.asp