JS
inheritance
Agenda
- Inheritance
- Polymorphism
Inheritance
Является способом повторного использования кода существующих объектов или для определения подтипа существующего объекта или того и другого, в зависимости от поддержки языка программирования.
Prototype
Это obj от которого наследуют свойства другие obj.
По умолчанию у каждого obj есть свой прототип.
Prototype
Прототип работает как резервное хранилище свойств. Если свойства нет у объекта - оно ищется в его прототипе. Получается наследование.
Prototype chain
var obj = {
name: 'Arni'
};
Наследование реализуется через скрытую ссылку __proto__
получили прототип нашего obj
конечная точка -> прототип прототипа null
Prototype
- Ссылка на прототип создается оператором new во время создания объекта.
- Ее значением становится свойство prototype функции-конструктора. Значение prototype указывает, от кого будут наследовать новые объекты
- Прототип работает как резервное хранилище свойств. Если свойства нет у объекта - оно ищется в его прототипе. Получается наследование.
Prototype
- Использовать ссылку __proto__ нельзя, вместо нее нужно использовать свойство prototype.
- Свойство prototype нужно для того что бы указать откуда брать прототип.
Function Constructor
// Function constructor
var Person = function() {
this.name = 'Arni';
};
var person = new Person();
console.log(person.name);
Inheritance
var Person = function() {
this.name = 'Arni';
};
var person = new Person();
console.log(person.name);
var personInfo = {
name: 'Vik',
getName: function() {
return this.name;
}
};
Person.prototype = personInfo;
var person2 = new Person();
console.log('person2', person2);
prototype
var Person = function() {
this.name = 'Arni';
};
var person = new Person();
console.log(person.name);
var personInfo = {
name: 'Vik',
getName: function() {
return this.name;
}
};
Person.prototype = personInfo;
var person2 = new Person();
console.log('person2', person2);
В person нового obj не будет так как добавляем в прототип после оператора new. Новый обьект будет в прототипе person2.
Inheritance
var NewPerson = function() {
this.name = 'Arni';
};
var PersonInfo2 = function() {
this.name = 'Team';
this.getName = function() {
return this.name;
}
};
NewPerson.prototype = new PersonInfo2();
var newPerson = new NewPerson();
console.log('newPerson', newPerson);
console.log('newPerson.getName()',
newPerson.getName());
Inheritance
var animal = {
canRun: true
};
// создадим Волка
var Wolf = function() {
this.name = 'wolf';
};
// создадим еще одного Волка
var GreyWolf = function() {
this.color = 'grey';
};
var BlackWolf = function() {
this.color = 'black';
};
// наследуем от animal
Wolf.prototype = animal;
var wolf = new Wolf();
GreyWolf.prototype = wolf;
BlackWolf.prototype = wolf;
var wolfyGrey = new GreyWolf();
var blackGrey = new BlackWolf ();
console.log(wolf);
console.log(wolfyGrey);
console.log(blackGrey);
Detect property source
hasOwnProperty
wolfyGrey.hasOwnProperty('color'); // true
wolfyGrey.hasOwnProperty('name'); // false
Prototype methods and properties are captured by for..in loop, so if you don't need them - use hasOwnProperty.
for (var key in wolfyGrey) {
console.log(key + ' = ' + wolfyGrey[key]); // we see all properties
}
for (var key in wolfyGrey) {
if (wolfyGrey.hasOwnProperty(key)) {
console.log(key + ' = ' + wolfyGrey[key]); // show only own props
}
}
Detect property source
instanceof
// проверка свойств от которого obj были созданы
console.log(wolfyGrey instanceof GreyWolf); // true
console.log(wolfyGrey instanceof Person); // false
Constructor
Constructor ссылается на ту функцию от которой obj был создан
var TestFunct = function() {
this.testProp = 'test prop';
};
console.log(TestFunct.prototype);
console.log(TestFunct.prototype.constructor === TestFunct);
Не рекомендуется использовать данное свойство
Constructor
var TestFunct = function() {
this.testProp = 'test prop';
};
var testObj = {
constructor: 'new constructor'
};
TestFunct.prototype = testObj;
console.log(TestFunct.prototype);
console.log(TestFunct.prototype.constructor === TestFunct);
// false
Пример того почему лучше не использовать свойство constructor
Inheritance
Object.create()
// for new IE
var wolf2 = {
canRun: true
};
var dog = Object.create(wolf2);
console.log('dog canRun: ', dog.canRun);
function inherit(proto) {
// создаем временный конструктор, который возвращает пустой obj,
// в качесте прототипа устанавливаем тот прототип который передали
function F() {} // для того что бы вернуть пустой обьект, когда вызовем через new
F.prototype = proto;
return new F();
}
var dog2 = inherit(wolf2);
console.log('dog2 canRun: ', dog2.canRun);
Polyfill
Defining an object template
// Function constructor
function Person(firstName, lastName, age, gender, interests) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.gender = gender;
this.interests = interests;
};
// adding methods
Person.prototype.bio = function() {
return this.firstName + ' ' + this.lastName + 'is ' + this.age + ' years old. They like ' + this.interests;
}
Person.prototype.greeting = function() {
return 'Hi I am ' + this.firstName + ' ' + this.lastName;
}
Creating actual objects
// creat person
var person = new Person('Arni', 'Sv', 31,
'male', 'actor')
var person2 = new Person('David', 'Sv', 30,
'male', 'sport')
// проверим принадлежность к классу Person
console.log(person instanceof Person)
// => true
// call methods
console.log(person.bio());
console.log(person2.bio());
Specialist classes
В этом случае нам не нужны общие люди - мы хотим учителей и студентов, которые являются более конкретными типами людей. В ООП мы можем создавать новые классы на основе других классов - эти новые дочерние классы могут быть сделаны для наследования функций данных и кода их родительского класса, поэтому вы можете повторно использовать функциональные возможности, общие для всех типов объектов, а не дублировать их. Если функциональность отличается между классами, вы можете определить специализированные функции непосредственно для определенного obj по мере необходимости
Polymorphism
Возможность объектов с одинаковой спецификацией иметь различную реализацию.
Язык программирования поддерживает полиморфизм, если классы с одинаковой спецификацией могут иметь различную реализацию — например, реализация класса может быть изменена в процессе наследования.
Кратко смысл полиморфизма можно выразить фразой: «Один интерфейс, множество реализаций».
Specialist classes
Specialist classes
function Teacher(firstName, lastName, age, gender, interests, subject) {
Person.call(this, firstName, lastName, age, gender, interests);
// отнаследовать
// в данном подходе есть нюанс
// Наследник не имеет доступа к приватным свойствам родителя.
// (денлаем их через this._variable)
this.subject = subject;
}
// Если в Person через prototype были добавлены методы то их не отнаследует так как
// через call прототип не наследуется
Teacher.prototype = Object.create(Person.prototype);
Teacher.prototype.constructor = Teacher;
Teacher.prototype.greeting = function() {
return 'Hello my name is ' + this.firstName + ' ' + this.lastName +
'and I teach ' + this.subject;
};
var teacher = new Teacher('Arni', 'Sv', 30, 'male', 'actor', 'programmer');
console.log(teacher);
Teacher
Specialist classes
function Student(firstName, lastName, age, gender, interests) {
Person.apply(this, arguments); // отнаследовать
// или Person.apply(this, [firstName, lastName, age, gender, interests]);
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.greeting = function() {
return 'Yo! I\'m ' + this.firstName + ' ' + this.lastName;
};
var student = new Student('Arni', 'Sv', 20, 'male', 'programming');
console.log(student);
Student
Specialist classes
Specialist classes
class Person {
constructor(firstName, lastName, age, gender, interests) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.gender = gender;
this.interests = interests;
}
greeting() {
console.log('Hello');
}
};
class Student extends Person {
greeting() {
console.log(`Hello, I am ${this.firstName}`);
}
}
let student = new Student('Vic', 'D', 23, 'm', 'sport')
super
class Person {
constructor(firstName, lastName, age, gender, interests) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.gender = gender;
this.interests = interests;
}
greeting() {
console.log('Hello');
}
};
class Student extends Person {
constructor(firstName, lastName, age, gender, interests, className) {
super(firstName, lastName, age, gender, interests);
this.className = className;
}
greeting() {
console.log(`Hello, I am ${this.firstName}`);
}
}
let student = new Student('Vic', 'D', 23, 'm', 'sport', '5')
Links
- http://javascript.ru/tutorial/object/inheritance
- https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance
- https://developer.mozilla.org/ru/docs/Learn/JavaScript/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B/Object-oriented_JS
- https://learn.javascript.ru/functional-inheritance
- http://eloquentjavascript.net/06_object.html
- https://www.youtube.com/watch?v=wfMtDGfHWpA
Examples
Inheritance in JS
By Oleg Rovenskyi
Inheritance in JS
- 772