2. Об’єкт може успадковувати властивості іншого
об’єкта.
Спеціальна властивість __proto__ дозволяє
призначити об’єкту інший об’єкт як прототип.
Приклад:
var animal = {
isHungry: true,
legsNumber: 4
};
var indyk = {
canFly: true
};
indyk.__proto__ = animal;
alert( "indyk.canFly = " + indyk.canFly ); // true
alert( "indyk.isHungry = " + indyk.isHungry ); // true
alert( "indyk.legsNumber = " + indyk.legsNumber ); // 4
3. Тут animal є прототипом для indyk. Або по-
іншому: indyk “прототипно успадковує” властивості
isHungry і legsNumber від animal.
Але ми можемо переписати властивість, яка
визначена у прототипі:
indyk.legsNumber = 2;
alert( "indyk.legsNumber = " + indyk.legsNumber ); // 2
При цьому:
alert( "animal.legsNumber = " + animal.legsNumber ); //
4
4. Object.create(null)
Нерідко треба створити об’єкт як колекцію пар ключ-
значення:
var kolobok = {};
kolobok.health = 50;
kolobok.name = "Колобок";
При цьому об’єкт має крім призначених властивостей (healt і
name) ще й “ліві”, які походять від вбудованих функцій.
Наприклад:
kolobok.toString;
kolobok.__proto__;
Щоб цього уникнути, можна створювати об’єкти без прототипів:
var kolobok = Object.create(null);
Тоді:
alert( kolobok.toString ); // undefined
alert( kolobok.__proto__ ); // undefined
5. Створення об’єктів через new
Частіше об’єкти створюються не через {...}, а
функцією-конструктором з використанням new. В
цьому випадку теж можна вказувати прототип.
function Vovk(name) {
this.name = name;
this.__proto__ = animal;
}
var vovk = new Vovk("Вовчик-братик");
alert( vovk.isHungry ); // true, з прототипа
Тут маємо проблему сумісності з IE10.
6. Крос-браузерний спосіб – призначити прототип
конструктору:
function Vovk(name) {
this.name = name;
}
Vovk.prototype = animal;
var vovk = new Vovk("Вовчик-братик");
alert( vovk.isHungry ); // true, з прототипа
7. Властивість constructor
Ця властивість дозволяє створювати об’єкт за тим
самим конструктором, що й вказаний (без
прописування самого конструктора).
function Vovk(name) {
this.name = name;
}
var vovk = new Vovk("Вовчик-братик");
var vovk2 = new vovk.constructor("Сірий вовк");
alert ( vovk2.name ); // Сірий вовк
Це може бути корисно, якщо конструктор точно не
відомий, наприклад, прописаний поза нашим кодом.
8. Зауваження до попереднього прикладу.
function Vovk(name) {
this.name = name;
}
Vovk.prototype = animal;
var vovk = new Vovk("Вовчик-братик");
var vovk2 = new vovk.constructor("Сірий вовк");
alert ( vovk2.name ); // undefined
Маємо undefined, бо vovk2 шукає constructor у
себе, але не знаходить, тоді, згідно з prototype
шукає його у animal, але там його нема.
9. prototype дозволяє вказати методи і властивості,
потрібні для всіх об’єктів класу.
Властивість можна прописати в конструкторі:
function Animal(name) {
this.name = name;
}
Але можна додати її й пізніше:
function Animal(name) {
this.name = name;
}
Animal.prototype.legsNumber = 4;
Так само можна з методом:
Animal.prototype.sayHi = function() {
alert( "Привіт, мене звати " + this.name );
};
10. Клас і екземпляр класу
у функціональному стилі (повторення)
function Animal(name) {
this.name = name;
this.isHungry = true;
this.sayHi = function() {
alert( "Привіт, мене звати " + this.name );
};
}
var vovk = new Animal("Вовк");
vovk.sayHi();
11. Це саме у прототипному стилі
function Animal(name) {
this._name = name;
this._isHungry = true;
}
Animal.prototype.sayHi = function() {
alert( "Привіт, мене звати " + this.name );
}
var vovk = new Animal("Вовк");
vovk.sayHi();
Властивості name і isHungry будуть зберігатись у
vovk, а загальні методи – в прототипі.
12. Тут замість name і isHungry у конструкторі
використано _name і _isHungry. Символом “_” на
початку позначають так звані захищені властивості.
У методі в прототипі Animal.prototype.sayHi
використовується name береться з конструктора, для
якого ця властивість знаходиться зовні. Тому name
записують в сам об’єкт, позначаючи як захищену
властивість.
Звичайно, це тільки питання домовленості, бо
відсутність символу “_” не змінила б працездатності
програми.
13. Задача 89
1. Напишіть у процедурному стилі
конструктор Animal з захищеною
властивістю legsNumber (кількість ніг).
2. Створіть сеттер для цієї властивості.
3. Створіть ґеттер, який повертає зразу
ім’я і кількість ніг.
4. Створіть чотирилапого зайця і
дволапого індика.
15. Задача 90.0
Для конструктора класу
function Animal(name) {
this._name = name;
this._mass = 1;
}
напишіть ґеттер-сеттер mass().
Створіть 5-кілограмовго зайця і 3-кілограмового
індика. Перевірте роботу методу mass().
16. Розв’язок
function Animal(name) {
this._name = name;
this._mass = 1;
}
Animal.prototype.mass = function(newMass) {
if (!arguments.length) return this._mass;
if(newMass < 0) {
alert ("Не може бути");
} else {
this._mass = newMass;
}
}
var zayets = new Animal("Заєць");
zayets.mass(5);
var indyk = new Animal("Індик");
indyk.mass(3);
17. Задача 90.1
Напишіть фунцію meet(animal1, animal2),
результатом роботи якої є “відкушування”
важчою твариною половини маси легшої
тварини. Порядок аргументів повинен бути
довільним.
18. Розв’язок
meet(zayets, indyk);
function meet(animal1, animal2) {
var mass1 = animal1.mass();
var mass2 = animal2.mass();
if (mass1 > mass2) {
animal1.mass(mass1 + mass2/2);
animal2.mass(mass2/2);
} else if (mass2 > mass1) {
animal2.mass(mass2 + mass1/2);
animal1.mass(mass1/2);
}
}