g1er / Andrew

0 stars 0 forks source link

Прототипы #8

Closed IgorKulishov closed 6 years ago

IgorKulishov commented 6 years ago

Прототипы

"В дополнение к набору свойств, у всех конструкторов / классов в JavaScript есть свойство prototype ("прототип"), которое содержит набор свойств, которые будут унаследованы новыми объектами создаными на основе этих конструкторов / классов. Примечание: термин "класс" был введен в версии JavaScript ES6 для того что бы создать схожий с объектно-ориентированных языками синтаксис (название Class используется в Java, C# ).

Объекты созданные на базе конструкторов содержат свойство :

__proto__

это свойство показывается историю происхождения.

Далее приведем примеры : 1) Откроем консоль и скопируем конструктор созданный тобою в предыдущем задании.

function Swimmer(style, distance) {
    this.style = style;
    this.distance = function() {
        console.log("This swimmer prefer " + distance + " " + this.style)
    }
}

Далее вызовем свойство конструктора prototype:

Swimmer.prototype

Раскрой полученный объект - ты увидешь что там содержатся объекты: "constructor" и внутри его свойства "prototype".

2) Теперь создадим объект lamer на основе конструктора Swimmer

var lamer = new Swimmer('snaky', 10);

После чего просмотрим свойства объекта:

lamer.__proto__

Это свойство не используется на прямую и как правило только используется браузером. Не рекомендуется использовать на прямую это свойство в коде.

3) Добавим теперь по одному новому свойству и метод в существующий конструктор Swimmer используя следующий синтез:

Swimmer.prototype.record = ' world record ';
Swimmer.prototype.training = function() {
   console.log('To get ' + this.record + ' for ' + this.style + ' takes efforts ');
}

lamer.record;

lamer.training();

Как мы видем новые свойство и метод объекта доступны несмотря на то что объект был определен ранее (до того как были присвоены новые свойство и метод).

Поробуй с разными объектами, напиши свои вопросы.

g1er commented 6 years ago

Когда я изучал JS, я проходил этот prototype. Как мне объясняли (в более простой форме), он используется для того, чтобы создавать/добавлять дополнительные свойства и функции к классу, от которого потом создаются объекты. Т.е. если мы напишем Swimmer.prototype.record = "New World Record"; то свойство record появится и у lamer, и у bflySwimmer, и у всех остальных. Но тогда в чем отличие от того, что мы можем подняться наверх, где мы создавали класс Swimmer, и прописать там свойство record? Или по сути это одно и то же?

А насчет proto я раньше ничего не слышал. Он на практике вообще используется или существует просто для того, чтобы при необходимости к нему обратиться?

IgorKulishov commented 6 years ago

Да, совершенно верно, тебе правильно объяснили и ты правильно понял. Ты правильно понял что свойства "record" можно определить как внутри конструктора так и добавив отдельно после того как определен конструктор при помощи Swimmer.prototype.record. Тем не менее важно понимать что в JavaScript понятие класса / конструктора отличается от понятия классов в ОО (объектно-ориентированных) языках. Так в ОО после того как был создан объект от конструктора, свойства созданых объектов не будут меняться если мы добавим новые свойства в конструктор. В JavaScript как ты видешь мы можем добавить свойство в конструктор через prototype - после чего меняются свойства всех ранее образованных от этого класса объектов. В JavaScript "классы" введены для грубого подражания ОО языкам.

IgorKulishov commented 6 years ago

Cмотри объяснение " proto " выше - я обновил текст

IgorKulishov commented 6 years ago

Прочитав статью https://www.phpied.com/3-ways-to-define-a-javascript-class/ я решил немного отредактировать свой комментарий

Важно отметить что, если при помощи конструктора и его аргументов удобно создавать уникальные значения свойств новых объектов , то при помощи prototype удобно создавать общие свойства объектов.

Как пишет автор статьи: _A drawback of 1.1. is that the method getInfo() is recreated every time you create a new object. Sometimes that may be what you want, but it's rare. A more inexpensive way is to add getInfo() to the prototype of the constructor function.**_ Т.е. тут говориться (по мнению автора о преимуществе в п.1.2 над п.1.1) что конструктор (можешь проверить пример по ссылке в п.1.1. и так же я привожу его ниже) имеет недостаток, в том что приходиться несколько раз вводить один и тот же метод для каждого нового объекта.

function Apple (size, color) {
    this.size= size;
    this.color = color;
    this.getInfo = function() {
        return this.color + ' ' + this.type + ' apple';
    };
}

На самом деле это не так, ты определяешь конструктор / класс один раз в коде и создаешь новые объекты ссылаяст на название этого класса:

var bigRedApple = new Apple("big", "red");
var smallGreenApple = new Apple("small", "green");

Другое дело что вложенные свойства классов выглядят по разному, но ведут себя одинаково:

Т.о. разницу я существенно не вижу, кроме того скажу что мне нравиться больше визуально (легче читать код), когда все свойства определены внутри одного объекта как в случае с конструктором (но это мое мнение, как говорят про JavaScript что писался он многими и в нем есть хорошие и не очень хорошие правила применения (patterns) ).

IgorKulishov commented 6 years ago

Еще интересный оператор, который возвращает протип конструктора который его создал: "Object.getPrototypeOf(objectName)". Можно провести интересный эксперимент а) извлечь прототив из lamer :Object.getPrototypeOf(lamer) b) добавить свойство через prototype: Swimmer.prototype.weight = function(weight) { return weight; } c) еще раз извлечь прототив из lamer :Object.getPrototypeOf(lamer) На этот раз мы увидем что добавился weight

IgorKulishov commented 6 years ago

Комментарии на комментарии:

Но имей ввиду что, но мы будем изучать TypeScript, который имеет стиль ОО программирования (менее похожий на JavaScript и более Java).

Что под "стиль ОО программирования" понимается: а) классы - это могут быть чертежи домов с различными свойствами и методоами на основе которых могут строить дома: количество окон, этажей, дверей и т.д. б) объекты - это сами дома созданные на основе классов (каждый дом имеет определенные при создании значения свойств и методов). Как хороший инженер ты хотел бы знать заранее полный список свойств и методов классов (до начала строительства). Теперь представь себе что ты построил дома и тут появляется prototype который "подсовывает" новые свойства объектам (размер заднего двора, высота потолка, высота ступеней и т.д.). Вопрос тебе как инженеру : сможешь ли ты добиться при таких условиях передачу объектов соответствющих измененным условиям потребителям (возможно что переменные уже были использованы до того как добавилось новое свойство через prototype.

Я описал тебе опасения, которые видит перед собой человек работающий с объектно-оринтированными языками, такой специалист привык сначала четко определить все свойства классов, затем создавать объекты на основе этих классов и затем передавать объекты ф-циям.

Поэтому был создан синтакс классов в JavaScript ES6 и так же язык TypeScript, который имеет синтакс объектно-ориентированного языка, но на самом деле под капотом он компелируется в JavaScript (ES5 или ES6 на выбор). В обоих JavaScript ES6 и так же язык TypeScript существуют классы. Agular использует TypeScript. Поэтому мы будем изучать JavaScipt ES6 и TypeScript

Пиши если есть вопросы. Можешь почитать раздел книги для глубины познаний https://habrahabr.ru/post/241587/