Upload
igor-shkulipa
View
105
Download
0
Embed Size (px)
Citation preview
Темы лекции: ООП в JavaScript.
Тренер: Игорь Шкулипа, к.т.н.
JavaScript. Базовый курс
Занятие 4
http://www.slideshare.net/IgorShkulipa 2
ООП – это парадигма программирования, основанная напредставлении предметной области в виде взаимосвязанных абстрактныхобъектов и их реализаций.
В ООП вводится понятие Класса – пользовательского типаданных, объединяющего данные и методы их обработки.
Объектом называется экземпляр класса.
Объектно-ориентированное программирование
http://www.slideshare.net/IgorShkulipa 3
Члены-данные (поля) (data members) хранят всю необходимуюинформацию об объекте, формируют его состояние, характеристики ит.п.
Изменение состояния объекта или его характеристик связано сизменением данных, которые в нем содержатся.
Метод объекта (methods) – программный код, выполненный ввиде функции, реагирующий на передачу объекту определенногосообщения.
Вызов метода объекта может приводить к изменению егосостояния (значение членов-данных), а может и не приводить
Класс может содержать один или более методов, позволяющихосуществлять манипуляцию данными объекта
Поля и методы класса
http://www.slideshare.net/IgorShkulipa 4
Свойство – составляющая часть объекта, доступ к которойосуществляется как к члену объекта, но таковым не является (реализуютпринцип инкапсуляции для членов объекта).
В некоторых объектно-ориентированных языкахпрограммирования (например, в C++) свойства, как элемент языка,отсутствуют.
В этом случае в класс добавляют методы, посредством которыхосуществляется доступ к необходимым переменным класса.
Свойства
http://www.slideshare.net/IgorShkulipa 5
• Абстракция данных• Инкапсуляция• Наследование• Полиморфизм
Принципы ООП
http://www.slideshare.net/IgorShkulipa 6
Объекты представляют неполную информацию о реальныхсущностях предметной области.
Абстракция позволяет оперировать с объектном на уровне,адекватном решаемой задаче.
Высокоуровневые обращения к объекту могут обрабатываться спомощью вызова функций и методов низкого уровня.
В основе реализации этого принципа лежит использованиеабстрактных классов интерфейсов.
Абстракция данных
http://www.slideshare.net/IgorShkulipa 7
Инкапсуляция – объединение в одной оболочке данных иметодов их обработки, а так же способность объекта скрывать внутреннееустройство своих полей и методов.
Согласно данному принципу, класс должен рассматриваться какчерный ящик.
Внешний пользователь не знает детали реализации объекта иработает с ним только путем предоставленного объектом интерфейса (илиоткрытых методов доступа).
Следование данному принципу может уменьшить число связеймежду классами и упростить их независимую реализацию, модификацию итестирование.
Инкапсуляция
http://www.slideshare.net/IgorShkulipa 8
Наследование позволяет описать новый класс на основе ужесуществующего родительского (базового) класса.
Класс-потомок может добавить свои собственные свойства иметоды, а так же пользоваться методами и свойствами базового класса.
Наследование позволяет строить иерархии классов.
Наследование
http://www.slideshare.net/IgorShkulipa 9
Полиморфизмом называют явление, при котором классы-потомки могут изменять реализацию метода класса-предка, сохраняя егоинтерфейс.
Полиморфизм позволяет обрабатывать объекты классов-потомковкак однотипные объекты, не смотря на то, что реализация методов у нихможет различаться.
Полиморфизм
http://www.slideshare.net/IgorShkulipa 10
Доступ к данным и методам класса извне может быть ограничен
Рекомендуется запрещать доступ к данным класса в обход егометодов
Для разделения прав доступа к полям класса используютсямодификаторы доступа
public
private
protected
Доступ к данным и методам класса
http://www.slideshare.net/IgorShkulipa 11
public-методы и данные класса определяют его интерфейс доступк ним возможен из любой части кода.
Необходимо помещать в public-раздел класса тольконеобходимый набор методов, выполняющих высокоуровневые операциинад объектом класса
Открытые (public) поля и методы класса
http://www.slideshare.net/IgorShkulipa 12
private-данные и методы класса определяют его реализацию
Доступ к ним разрешен только из методов данного класса
Рекомендуется все данные класса делать закрытыми, ихобработку осуществлять внутри методов.
Закрытые методы класса обычно используются публичнымиметодами, решая внутренние задачи класса.
Закрытые (private) поля и методы класса
http://www.slideshare.net/IgorShkulipa 13
protected-данные и методы определяют интерфейс дляпроизводных классов.
Доступ к ним разрешен внутри методов данного класса и всех егопотомков.
В защищенной зоне размещают методы, которые не должны бытьвидны снаружи класса, но реализация которых может бытьпереопределена или использована производными классами.
Защищенные (protected) поля и методы класса
http://www.slideshare.net/IgorShkulipa 14
Класс – тип данных.Объект – переменная этого типа.
Для инициализации состояния объекта в момент его созданиясуществует специальный метод – конструктор. Конструктор имеет то жеимя, что и имя класса.
Конструктор вызывается в момент создания экземпляра класса(объявление переменной класса или вызов оператора new).
Некоторые определения
http://www.slideshare.net/IgorShkulipa 15
• Нет классов, но можно их эмулировать.• Есть наследование на прототипах - делегирующее прототипное
наследование• Все можно менять во время работы
• Цепочку наследования можно менять• Прототипы можно менять• В классах так сделать нельзя• Можно изменить прототипы базовых "классов“
• Любой объект имеет ссылку на прототип• Делегирование
• Мы можем пользоваться функциями прототипа не имеясобственных
• Цепочка прототипов• Каждый прототип - это тот же объект• Который также может иметь прототип• У прототипа прототипа также может быть прототип
Особенности ООП в JavaScript
http://www.slideshare.net/IgorShkulipa 16
Объекты JavaScript представляют собой наборы свойств иметодов. Можно сказать, что свойства объектов - это данные,связанные с объектом, а методы - функции для обработки данныхобъекта.
В общем случае, объект – это неупорядоченная коллекция парключ-значение.
var o = {
firstName : ”Василий”,
lastName : ”Пупкин”,
age : 30,
};
Object
http://www.slideshare.net/IgorShkulipa 17
Пустой объект:var o = new Object(); // то же, что и {}
Пустой массив:var a = new Array(); // то же, что и []
Дата/время:var d = new Date(); // текущее время
Создание объектов с помощью new
http://www.slideshare.net/IgorShkulipa 18
var o = {
name:"Ivan",
surname:"Ivanov"
};
alert(o.name);
o.surname = "Petrov";
alert(o.surname);
Доступ к свойствам
http://www.slideshare.net/IgorShkulipa 19
var o = {
name:"Ivan",
surname:"Ivanov"
};
alert(o["name"]);
o["surname"] = "Petrov";
alert(o["surname"]);
Объекты как ассоциативные массивы
http://www.slideshare.net/IgorShkulipa 20
var o = {
name:"Ivan",
surname:"Ivanov"
};
for (var prop in o){
alert(prop);
alert(o[prop]);
}
Объекты как ассоциативные массивы
http://www.slideshare.net/IgorShkulipa 21
var o = {
name:"Ivan",
surname:"Ivanov"
};
o.middle = "Ivanovich";
o.gender = "Male";
for (var prop in o){
alert(o[prop]);
}
Добавление свойств
http://www.slideshare.net/IgorShkulipa 22
var o = {
name:"Ivan",
surname:"Ivanov"
};
o.middle = "Ivanovich";
o.gender = "Male";
delete o.gender;
delete o["middle"];
delete o["someprop1"];
delete o.someprop2;
for (var prop in o){
alert(o[prop]);
}
Удаление свойств
http://www.slideshare.net/IgorShkulipa 23
this возвращает ссылку на объект, являющийся текущимконтекстом вызова. Это позволяет обращаться к свойствам "текущего"объекта: this.property.
Текущий объект не является жестко фиксированным и зависит отконтекста вызова функции. Он является, своего рода, скрытымпараметром.
this
http://www.slideshare.net/IgorShkulipa 24
var o = {
name:"Ivan",
surname:"Ivanov"
};
o.middle = "Ivanovich";
o.gender = "Male";
o.alertme1 = function() {
alert(this.name);
}
o.alertme2 = alerto;
o.alertme1();
o.alertme2();
function alerto() {
alert(this.name);
}
Методы
http://www.slideshare.net/IgorShkulipa 25
Объекты в JavaScript можно организовать в цепочки так, чтобысвойство, не найденное в одном объекте, автоматически искалось бы вдругом.
Связующим звеном выступает специальное свойство __proto__.
Объект, на который указывает ссылка __proto__, называется«прототипом».
Прототип объекта
http://www.slideshare.net/IgorShkulipa 26
var o = {
name:"Ivan",
surname:"Ivanov"
};
var oproto = {
gender:"Male"
};
o.__proto__ = oproto;
for (var prop in o){
alert(o[prop]);
}
__proto__
http://www.slideshare.net/IgorShkulipa 27
var oproto = {
gender:"Male"
};
var o = Object.create (oproto, {
name:{
value:"Ivan",
writable:true,
configurable:true,
enumerable:true
},
surname:{
value:"Ivanov",
writable:true,
configurable:true,
enumerable:true
}
})
for (var prop in o){
alert(o[prop]);
}
Object.create()
http://www.slideshare.net/IgorShkulipa 28
Object.create(prototype, descriptors)
Дескрипторы свойств, присутствующие в объектах, бывают двух основныхтипов: дескрипторы данных и дескрипторы доступа.
Дескриптор данных — это свойство, имеющее значение, которое может быть (аможет и не быть) записываемым.
Дескриптор доступа — это свойство, описываемое парой функций — геттероми сеттером. Дескриптор может быть только чем-то одним из этих двух типов; он неможет быть одновременно обоими.
И дескриптор данных, и дескриптор доступа являются объектами. Ониобладают следующими обязательными ключами:
• configurable - равен true только в том случае, если тип этого дескрипторасвойства может быть изменён и если свойство может быть удалено изсодержащего его объекта. Значение по умолчанию установлено в false.
• enumerable - равен true только в том случае, если это свойство можно увидетьчерез перечисление свойств содержащего его объекта. Значение поумолчанию установлено в false.
Object.create()
http://www.slideshare.net/IgorShkulipa 29
Дескриптор данных также может содержать следующие дополнительные ключи:
• value - значение, ассоциированное со свойством. Может быть любымдопустимым значением JavaScript (числом, объектом, функцией и т.д.).Значение по умолчанию установлено в undefined.
• writable - равен true только в том случае, если значение, ассоциированноесо свойством, может быть изменено с помощью оператора присваивания.Значение по умолчанию установлено в false.
Дескриптор доступа также может содержать следующие дополнительные ключи:
• get - функция, используемая как геттер свойства, либо undefined, еслисвойство не имеет геттера. Возвращаемое значение функции будетиспользоваться как значение свойства. Значение по умолчанию установленов undefined.
• set - функция, используемая как сеттер свойства, либо undefined, еслисвойство не имеет сеттера. Функция принимает единственным аргументомновое значение, присваиваемое свойству. Значение по умолчаниюустановлено в undefined.
Object.create()
http://www.slideshare.net/IgorShkulipa 30
var oproto = {
gender:"Male"
};
var o = Object.create (oproto, {
name:{
value:"Ivan",
writable:true,
configurable:true,
enumerable:true
},
surname:{
value:"Ivanov",
writable:true,
configurable:true,
enumerable:true
}
})
oproto.gender="Not Set";
for (var prop in o){
alert(o[prop]);
}
Прототип
http://www.slideshare.net/IgorShkulipa 31
...
Object.defineProperty(o,
"middle", {
enumerable: true,
configurable: true,
writable: true,
value: "Ivanovich"
});
for (var prop in o){
alert(o[prop]);
}
Object.defineProperty
http://www.slideshare.net/IgorShkulipa 32
...
for (var prop in o){
if (o.hasOwnProperty(prop))
alert(o[prop]);
}
obj.hasOwnProperty(prop)
http://www.slideshare.net/IgorShkulipa 33
Все объекты базовый набор методов, например метод toString,которые находится, не в самом объекте, а в его прототипе obj.__proto__.
Объект Object.prototype — вершина иерархии, единственный, укоторого __proto__ равно null.
Поэтому говорят, что «все объекты наследуют от Object», а еслиболее точно, то от Object.prototype.
Object.prototype
http://www.slideshare.net/IgorShkulipa 34
Любая функция, кроме некоторых встроенных, может создать объект.
Для этого ее нужно вызвать через директиву new.
Такие функции еще называются конструкторами.
function FullName (name, surname, middle) {
this.name = name;
this.surname = surname;
this.middle = middle;
return this; // не обязательно
}
var fullName= new FullName (“Ivan“, “Ivanov”, “Ivanovich”);
Создание объектов с помощью функций
http://www.slideshare.net/IgorShkulipa 35
function FullName (name, surname, middle) {
this.name = name;
this.surname = surname;
this.middle = middle;
this.alertme = function (){
alert(this.name);
}
return this; // не обязательно
}
var o1= new
FullName("Ivan", "Ivanov", "Ivanovich");
var o2= new
FullName("Petr", "Petrov", "Petrovich");
o1.alertme();
o2.alertme();
Конструкторы
http://www.slideshare.net/IgorShkulipa 36
function FullName (name, surname, middle) {
this.name = name;
this.surname = surname;
this.middle = middle;
this.alertme = function (){
alert(this.name);
}
return {
name: "Sidor",
surname: "Sidorov",
middle: "Sidorovich",
alertme: function () {
alert(this.name);
}
};
}
var o1= new
FullName("Ivan", "Ivanov", "Ivanovich");
var o2= new
FullName("Petr", "Petrov", "Petrovich");
o1.alertme();
o2.alertme();
Конструкторы
http://www.slideshare.net/IgorShkulipa 37
Чтобы новым объектам автоматически ставить прототип,конструктору ставится свойство prototype.
При создании объекта через new, в его прототип __proto__записывается ссылка из prototype функции-конструктора.
Как правило, свойство prototype используется дляпредоставления базового набора функциональных возможностей классуобъектов. Новые экземпляры объекта "наследуют" поведение прототипа,присвоенного этому объекту.
F.prototype
http://www.slideshare.net/IgorShkulipa 38
var nameObj = { name: "", gender:""};
function Initials(name, middle){
this.name = name;
this.middle = middle;
}
function SurnName(name, surname){
this.name = name;
this.surname = surname;
}
Initials.prototype = nameObj;
SurnName.prototype = nameObj;
Initials.prototype.alertme = function () {
alert(this.name + " " +
this.surname + " " + this.gender);
}
var initials = new
Initials("Ivan", "Ivanovich");
var surnname = new
SurnName("Petr", "Petrov");
nameObj.gender = "male";
initials.alertme();
surnname.alertme();
nameObj.alertme();
Пример
http://www.slideshare.net/IgorShkulipa 40
В prototype по умолчанию всегда находится свойствоconstructor, указывающее на функцию-конструктор. Но, если мырассчитываем использовать это свойство, то при замене prototype черезObject.create нужно его явно сохранить.
obj.prototype = Object.create(null);
obj.prototype.constructor = Object;
JavaScript никак не использует свойство constructor. То есть,оно создаётся автоматически, а что с ним происходит дальше — это уженаша забота. В стандарте прописано только его создание.
В частности, при перезаписи obj.prototype = { } свойстваconstructor больше не будет.
Свойство constructor
http://www.slideshare.net/IgorShkulipa 41
var nameObj = { name: "", gender:""};
function Initials(name, middle){
this.name = name;
this.middle = middle;
}
function SurnName(name, surname){
this.name = name;
this.surname = surname;
}
SurnName.prototype = nameObj;
Initials.prototype.alertme = function () {
alert(this.name + " " + this.surname + " " +
this.gender);
}
var initials = new Initials("Ivan", "Ivanovich");
var surnname = new SurnName("Petr", "Petrov");
nameObj.gender = "male";
Пример
http://www.slideshare.net/IgorShkulipa 42
alert(surnname.constructor); // ???
alert(surnname.__proto__.constructor); // ???
alert(initials.constructor); // ???
alert(initials.__proto__.constructor); // ???
alert(surnname.hasOwnProperty("name")); // ???
alert(surnname.hasOwnProperty("surname")); // ???
alert(surnname.hasOwnProperty("toString")); // ???
alert(Object.prototype.isPrototypeOf(surnname)); // ???
Пример
http://www.slideshare.net/IgorShkulipa 43
alert(surnname.constructor);
alert(surnname.__proto__.constructor);
alert(initials.constructor);
alert(initials.__proto__.constructor);
alert(surnname.hasOwnProperty("name"));
alert(surnname.hasOwnProperty("surname"));
alert(surnname.hasOwnProperty("toString"));
alert(Object.prototype.isPrototypeOf(surnname));
Пример
http://www.slideshare.net/IgorShkulipa 44
Все, что добавляется в this является public
function FullName (name, surname, middle) {
this.name = name;
this.surname = surname;
this.middle = middle;
this.alertme = function (){
alert(this.name);
}
return this;
}
var o1= new
FullName("Ivan", "Ivanov", "Ivanovich");
var o2= new
FullName("Petr", "Petrov", "Petrovich");
o1.alertme();
o2.alertme();
public
http://www.slideshare.net/IgorShkulipa 45
Все, что объявляется внутри конструктора, включая его параметры, является private
function FullName (name, surname, middle) {
var fullName=name + " " + middle + " " + surname;
this.name = name;
this.surname = surname;
this.middle = middle;
this.alertme = function (){
alert(fullName);
}
return this;
}
var o1= new
FullName("Ivan", "Ivanov", "Ivanovich");
var o2= new
FullName("Petr", "Petrov", "Petrovich");
o1.alertme();
o2.alertme();
private
http://www.slideshare.net/IgorShkulipa 46
protected - это, по сути, public, отмеченный «_» в началеидентификатора. И мы «договариваемся» эти свойства не трогать.
function FullName (name, surname, middle) {
var fullName=name + " " + middle + " " + surname;
this.name = name;
this.surname = surname;
this.middle = middle;
this._fullName = fullName;
this.alertme = function (){
alert(this._fullName);
}
return this;
}
var o1= new
FullName("Ivan", "Ivanov", "Ivanovich");
var o2= Object.create(new
FullName("Petr", "Petrov", "Petrovich"));
o1.alertme();
alert(o2._fullName);
protected
http://www.slideshare.net/IgorShkulipa 47
function Name () {
var name;
this.getName = function () {
return name;
}
this.setName = function (nm) {
nm = nm || null;
if (nm && (nm.length > 0))
name=nm;
else name="";
}
}
var n1=new Name();
var n2=new Name();
var n3=new Name();
n1.setName();
n2.setName(2);
n3.setName("3");
alert(n1.getName());
alert(n2.getName());
alert(n3.getName());
Инкапсуляция
http://www.slideshare.net/IgorShkulipa 48
var n0 = Object.create(null,{
name:{
configurable: true,
enumerable: true,
get: function () {
return name + ", hello GET!";
},
set: function (nm) {
nm = nm || null;
if (nm && (nm.length > 0))
name=nm;
else name="Default";
}
}
});
n0.name="Ivan";
alert(n0.name);
n0.name="";
alert(n0.name);
Инкапсуляция 2
http://www.slideshare.net/IgorShkulipa 49
function Name () {
var name;
this.getName = function () {
return name;
}
this.setName = function (nm) {
nm = nm || null;
if (nm && (nm.length > 0))
name=nm;
else name="";
}
}
function FullName () {
Name.call(this);
var surname = "S";
var middle = "M";
this.getName = function (){
return name + " " +
middle + " " + surname;
}
}
Наследование
http://www.slideshare.net/IgorShkulipa 50
function Name () {
this._name="";
this.getName = function () {
return this._name;
}
this.setName = function (nm) {
nm = nm || null;
if (nm && (nm.length > 0))
this._name=nm;
else this._name="";
}
}
function FullName () {
Name.call(this);
var surname = "S";
var middle = "M";
this.getName = function (){
return this._name + " " +
middle + " " + surname;
} }
var n1= new FullName();
var n2= new FullName();
var n3= new FullName();
n1.setName();
n2.setName(2);
n3.setName("3");
alert(n1.getName());
alert(n2.getName());
alert(n3.getName());
Наследование
http://www.slideshare.net/IgorShkulipa 51
Сериализация (в программировании) — процесс переводакакой-либо структуры данных в последовательность битов. Обратной коперации сериализации является операция десериализации(структуризации) — восстановление начального состояния структурыданных из битовой последовательности.
Почти все языки программирования имеют библиотеки дляпреобразования объектов в формат JSON.
Основные методы для работы с JSON в JavaScript — это:
• JSON.parse — читает объекты из строки в формате JSON.
• JSON.stringify — превращает объекты в строку в формате JSON,
используется, когда нужно из JavaScript передать данные по сети.
Сериализация
http://www.slideshare.net/IgorShkulipa 52
JSON (JavaScript Object Notation) — текстовый формат обмена данными,основанный на JavaScript.
JSON строится на двух структурах:• Коллекция пар ключ/значение. В разных языках, эта концепция
реализована как объект, запись, структура, словарь, хэш, именованныйсписок или ассоциативный массив.
• Упорядоченный список значений. В большинстве языков это реализованокак массив, вектор, список или последовательность.
В JSON используются их следующие формы:• Объект — это неупорядоченное множество пар имя/значение,
заключённое в фигурные скобки { }. Между именем и значением стоитсимвол ": ", а пары имя/значение разделяются запятыми.
• Массив (одномерный) — это множество значений, имеющих порядковыеномера (индексы). Массив заключается в квадратные скобки [ ]. Значенияотделяются запятыми.
• Значение может быть строкой в двойных кавычках, числом, значениемtrue или false, объектом, массивом, или значением null. Эти структурымогут быть вложены друг в друга.
• Строка — это упорядоченное множество из нуля или более символовюникода, заключенное в двойные кавычки, с использованием escape-последовательностей начинающихся с обратной косой черты (backslash).Символы представляются простой строкой.
• Имя — это строка.
JSON
http://www.slideshare.net/IgorShkulipa 53
Пример 1.
var fio= {surname:‘Пупкин',name:‘Василий',middle:‘Борисович'};
Пример 2. Wikipedia.
{
"firstName": "Иван",
"lastName": "Иванов",
"address": {
"streetAddress": "Московское ш., 101, кв.101",
"city": "Ленинград",
"postalCode": 101101
},
"phoneNumbers": [
"812 123-1234",
"916 123-4567"
]
}
Примеры JSON
http://www.slideshare.net/IgorShkulipa 54
var initialsString= JSON.stringify(initials);
var surnnameString= JSON.stringify(surnname);
alert(initialsString);
alert(surnnameString);
var ini= JSON.parse(initialsString);
var sur= JSON.parse(surnnameString);
alert(ini.name);
alert(sur.name);
Сериализация
http://www.slideshare.net/IgorShkulipa 55
Ошибки в скриптах делятся на два типа:
• Синтаксические ошибки — когда нарушена структура кода.Обычно это ошибки программиста. Их также называют «ошибкивремени компиляции», поскольку они происходят на этаперазбора кода.
• Семантические ошибки, также называемые «ошибки временивыполнения» — возникают, когда браузер смог прочитать скрипти уже выполняет код, но вдруг натыкается на проблему.
Обработка исключений
http://www.slideshare.net/IgorShkulipa 56
• Выполняется код внутри блока try.• Если в нём возникнет ошибка, то выполнение try прерывается, и
управление прыгает в начало блока catch.
try {
alert("Start try");
a;
alert("End of try");
} catch (error) {
alert("Error catched!");
}
Конструкция try-catch. С ошибкой
http://www.slideshare.net/IgorShkulipa 57
try {
alert("Start try");
var a;
alert("End of try");
} catch (error) {
alert("Error catched!");
}
Конструкция try-catch. Без ошибок
http://www.slideshare.net/IgorShkulipa 58
У блока catch есть аргумент, в примере выше он обозначен error. Это — объект ошибки или, как ещё говорят, объект исключения (exception object).
Он содержит информацию о том, что произошло, и может бытьразным, в зависимости от ошибки.
Как правило, error — объект встроенного типа Error и производных от него.
Есть несколько свойств, которые присутствуют в объекте ошибки:
• name - тип ошибки. Например, при обращении к несуществующей переменной равен "ReferenceError".
• message - текстовое сообщение о деталях ошибки.
• stack - везде, кроме IE<9, есть также свойство stack, указывающее, где в точности произошла ошибка.
Объект ошибки
http://www.slideshare.net/IgorShkulipa 59
try {
alert("Start try");
a;
alert("End of try");
} catch (error) {
alert(error);
}
Объект ошибки
http://www.slideshare.net/IgorShkulipa 60
try {
alert("Start try");
var a = 1;
var b = a();
alert("End of try");
} catch (error) {
alert(error);
}
Объект ошибки
http://www.slideshare.net/IgorShkulipa 61
try {
alert("Start try");
var a = 1;
var b = a();
alert("End of try");
} catch (error) {
alert(error);
} finally {
alert("Finally");
}
Блок finally позволяет избежать дублирования кода в try-catch.
Секция finally
http://www.slideshare.net/IgorShkulipa 62
Блок finally срабатывает при любом выходе из try-catch, в том числе иreturn. Это гарантирует освобождение ресурсов в любом случае.
function f() {
try {
alert("Start try");
return 1;
} catch (error) {
alert(error);
} finally {
alert("Finally");
}
}
f();
finally и return
http://www.slideshare.net/IgorShkulipa 63
throw <объект ошибки>
Инициирует ошибку, которую можно поймать в catch. Объектом ошибки может быть что угодно, например число.
try {
alert("Start try");
throw 1;
} catch (error) {
alert(error);
} finally {
alert("Finally");
}
Генерация ошибок
http://www.slideshare.net/IgorShkulipa 64
В случае вложенных вызовов — не важно, где было исключение, оно будет поймано ближайшим внешним try-catch.
function f() {
while (true) {
throw 1;
}
}
try {
alert("Start try");
f();
} catch (error) {
alert(error);
} finally {
alert("Finally");
}
Всплывание ошибок
http://www.slideshare.net/IgorShkulipa 65
try {
try {
alert("Start try");
f();
alert("End try");
} catch (error) {
if (error instanceof String)
alert(error);
else throw error;
} finally {
alert("Finally");
}
} catch (err) {
alert(err + " external try");
}
Вложенные блоки try..catch
http://www.slideshare.net/IgorShkulipa 66
SOLID – это акроним названий пяти основных принциповпроектирования классов, сформулированных Робертом Мартином:
• Single responsibility (принцип одной ответственности),
• Open for extension and closed for modification (принципоткрытости/закрытости, или открытость для расширения изакрытость для модификации),
• Liskov substitution (принцип подстановки Лисков),
• Interface segregation (принцип разделения интерфейса),
• Dependency inversion (принцип инверсии зависимостей).
SOLID. Принципы проектирования
http://www.slideshare.net/IgorShkulipa 67
Принцип единственной ответственности (Single ResponsibilityPrinciple) часто определяют так: у объекта должна быть только однапричина для изменения; чем больше файл или класс, тем труднеедостичь этой цели.
Этот принцип говорит о том, что по-хорошему каждый классдолжен решать только одну задачу. Это совсем не значит, что в класседолжен быть всего один метод. Это означает, что методы класса должныбыть связаны одной общей целью.
Single Responsibility
http://www.slideshare.net/IgorShkulipa 68
Single Responsibility
Плохой пример Неплохой пример
function Persone(name, surname, middle) {
this.name=name;
this.surname=surname;
this.middle=middle;
return this;
}
Persone.prototype.LoadFromDatabase =
function () {}
Persone.prototype.SaveToDatabase =
function () {}
Persone.prototype.PrintToPrinter =
function () {}
function Persone(name, surname, middle) {
this.name=name;
this.surname=surname;
this.middle=middle;
return this;
}
function PersoneDatabase() {
return this;
}
PersoneDatabase.prototype.LoadFromDatabase =
function () { return new Persone(...);}
PersoneDatabase.prototype.SaveToDatabase =
function (p) { }
function PersonePrinter() {
return this;
}
PersonePrinter.prototype.PrintToPrinter =
function (p) { }
http://www.slideshare.net/IgorShkulipa 69
Объекты проектирования (классы, функции, модули и т.д.)должны быть открыты для расширения, но закрыты для модификации.
Этот принцип говорит о том, что классы нужно проектироватьтак, чтобы впоследствии иметь возможность изменять поведение класса,не изменяя его код.
Open for Extension and Closed for Modification
http://www.slideshare.net/IgorShkulipa 70
Open for Extension and Closed for Modification
Плохой пример Неплохой пример
function PersonePrinter () {
}
PersonePrinter.prototype.PrintToPrinter =
function (p) { }
function PersonePrinter () {
}
PersonePrinter.prototype.PrintToPrinter =
function (p) { }
PersonePrinter.prototype.PrintToPrinterShortForm =
function (p) { }
PersonePrinter.prototype.PrintToPrinterDetailedForm =
function (p) { }
function PersonePrinter () {
}
PersonePrinter.prototype.PrintToPrinter =
function (persone, printForm) { }
var PrintForm = { formats : [] }
function PrintFormGeneral () { }
PrintFormGeneral.prototype = PrintForm;
function PrintFormShort () { }
PrintFormShort.prototype = PrintForm;
function PrintFormDetailed () { }
PrintFormDetailed.prototype = PrintForm;
http://www.slideshare.net/IgorShkulipa 71
Функции, которые используют ссылки на базовые классы, должныиметь возможность использовать объекты производных классов, не зная обэтом.
Liskov Substitution
http://www.slideshare.net/IgorShkulipa 72
Liskov Substitution
Плохой пример Неплохой пример
function PersonePrinter () {
}
PersonePrinter.prototype.PrintToPrinter =
function (persone, printForm) {
//...
if (printForm instanceof PrintFormGeneral)
{ }
//...
if (printForm instanceof PrintFormShort)
{ }
}
function PersonePrinter () {
}
PersonePrinter.prototype.PrintToPrinter =
function (persone, printForm) {
//...
printForm.formatReport(persone);
//...
}
http://www.slideshare.net/IgorShkulipa 73
Interface Segregation
Плохой пример Неплохой пример
function Employee () {
this.UseComputer = function () { };
this.Develop = function () { };
this.Test = function () { };
}
function SoftDeveloper (){
Employee.call(this);
this.Develop = function() { }
this.Test = function() {/* How ? */ }
return this;
}
function SoftTester (){
Employee.call(this);
this.Develop = function() { /* How ? */ }
this.Test = function() { }
return this;
}
function Employee () {
this.UseComputer = function () { };
}
function SoftDeveloper (){
Employee.call(this);
this.Develop = function() { }
return this;
}
function SoftTester (){
Employee.call(this);
this.Test = function() { }
return this;
}
http://www.slideshare.net/IgorShkulipa 74
• Модули верхних уровней не должны зависеть от модулейнижних уровней.
• Оба типа модулей должны зависеть от абстракций.
• Абстракции не должны зависеть от реализаций.
• Реализации должны зависеть от абстракций.
Dependency Inversion
http://www.slideshare.net/IgorShkulipa 75
Dependency Inversion
Плохой пример Неплохой пример
function SoftDeveloper () {
this.Develop = function () { }
}
function Manager () {
var softDeveloper = new SoftDeveloper();
this.Manage = function() {
softDeveloper.Develop();
}
}
function SoftDeveloper () {
this.Develop = function () { }
}
function Manager (softDeveloper) {
var sd = softDeveloper;
this.Manage = function() {
sd.Develop();
}
}
http://www.slideshare.net/IgorShkulipa 76
Паттерн описывает задачу, которая снова и снова возникает в работе, а также принцип ее решения, причем таким образом, что это решение можно потомиспользовать много раз, ничего не изобретая заново.
В общем случае паттерн состоит из четырех основных элементов:
• Имя. Присваивание паттернам имен позволяет проектировать на более высокомуровне абстракции. С помощью имен паттернов можно вести общение с коллегами.Назначение паттернам имен упрощает общение в профессиональной среде.
• Задача - это описание того, когда следует применять паттерн. Необходимосформулировать задачу и ее контекст. Может описываться конкретная проблемапроектирования, например способ представления алгоритмов в виде объектов. Также задача может включать перечень условий, при выполнении которых имеетсмысл применять данный паттерн.
• Решение представляет собой описание элементов дизайна, отношений междуними, функций каждого элемента. Конкретный дизайн или реализация не имеютсяввиду, поскольку паттерн – это шаблон, применимый в самых разных ситуациях.
• Результаты - это следствия применения паттерна и разного рода компромиссы.Хотя при описании проектных решений о последствиях часто не упоминают, знатьо них необходимо, чтобы можно было выбрать между различными вариантами иоценить преимущества и недостатки данного паттерна.
Паттерны (шаблоны проектирования)
http://www.slideshare.net/IgorShkulipa 77
Паттерны проектирования программных систем делятся наследующие категории:
• Архитектурные паттерны. Описывают структурную схемупрограммной системы в целом. В данной схеме указываются отдельныефункциональные составляющие системы, называемые подсистемами, атакже взаимоотношения между ними.
• Паттерны проектирования. описывают схемы детализациипрограммных подсистем и отношений между ними, при этом они невлияют на структуру программной системы в целом и сохраняютнезависимость от реализации языка программирования.
• Идиомы - низкоуровневые паттерны, имеют дело с вопросамиреализации какой-либо проблемы с учетом особенностей данного языкапрограммирования.
Классификация паттернов
http://www.slideshare.net/IgorShkulipa 78
Паттерны проектирования делятся на следующие категории:
• Порождающие - шаблоны проектирования, которые абстрагируютпроцесс создания объектов. Они позволяют сделать систему независимойот способа создания, композиции и представления объектов.
• Структурные - шаблоны проектирования, в которых рассматриваетсявопрос о том, как из классов и объектов образуются более крупныеструктуры.
• Поведенческие - шаблоны проектирования, определяющиеалгоритмы и способы реализации взаимодействия различных объектов иклассов.
Паттерны проектирования (GoF)
http://www.slideshare.net/IgorShkulipa 79
• Singleton (Одиночка) - контролирует создание единственногоэкземпляра некоторого класса и предоставляет доступ к нему.
• Factory Method (Фабричный метод) - В его классическом вариантевводится полиморфный класс Factory, в котором определяетсяинтерфейс фабричного метода, а ответственность за созданиеобъектов конкретных классов переносится на производные от Factoryклассы, в которых этот метод переопределяется.
• Abstract Factory (Абстрактная фабрика) - использует несколькофабричных методов и предназначен для создания целого семействаили группы взаимосвязанных объектов.
• Builder (Строитель) - определяет процесс поэтапного конструированиясложного объекта, в результате которого могут получаться разныепредставления этого объекта.
• Prototype (Прототип) - создает новые объекты с помощью прототипов.Прототип - некоторый объект, умеющий создавать по запросу копиюсамого себя.
• Object Pool (Пул объектов) - используется в случае, когда созданиеобъекта требует больших затрат или может быть создано толькоограниченное количество объектов некоторого класса.
Порождающие паттерны
http://www.slideshare.net/IgorShkulipa 80
• Adapter представляет собой программную обертку над ужесуществующими классами и предназначен для преобразования ихинтерфейсов к виду, пригодному для последующего использования вновом программном проекте.
• Bridge отделяет абстракцию от реализации так, что то и другоеможно изменять независимо.
• Composite группирует схожие объекты в древовидные структуры.Рассматривает единообразно простые и сложные объекты.
• Decorator используется для расширения функциональности объектов.Являясь гибкой альтернативой порождению классов, паттернDecorator динамически добавляет объекту новые обязанности.
• Facade предоставляет высокоуровневый унифицированныйинтерфейс к набору интерфейсов некоторой подсистемы, чтооблегчает ее использование.
• Flyweight использует разделение для эффективной поддержкимножества объектов.
• Proxy замещает другой объект для контроля доступа к нему.
Структурные шаблоны проектирования
http://www.slideshare.net/IgorShkulipa 81
• Паттерн Chain of Responsibility позволяет обработать запроснескольким объектам-получателям. Получатели связываются вцепочку, и запрос передается по цепочке, пока не будет обработанкаким-то объектом. Паттерн Chain of Responsibility позволяет такжеизбежать жесткой зависимости между отправителем запроса и егополучателями.
• Паттерн Command преобразовывает запрос на выполнение действия вотдельный объект-команду. Это придает системе гибкость: позволяетосуществлять динамическую замену команд, использовать сложныесоставные команды, осуществлять отмену операций.
• Паттерн Iterator предоставляет механизм обхода элементов составныхобъектов (коллекций) не раскрывая их внутреннего представления.
• Паттерн Interpreter предназначен для решения повторяющихсязадач, которые можно описать некоторым языком. Для этого паттернInterpreter описывает решаемую задачу в виде предложений этогоязыка, а затем интерпретирует их.
• Паттерн Mediator инкапсулирует взаимодействие совокупностиобъектов в отдельный объект-посредник. Уменьшает степеньсвязанности взаимодействующих объектов - им не нужно хранитьссылки друг на друга.
Шаблоны поведения
http://www.slideshare.net/IgorShkulipa 82
• Паттерн Memento получает и сохраняет за пределами объекта еговнутреннее состояние так, чтобы позже можно было восстановить объект втаком же состоянии.
• Паттерн Observer определяет зависимость "один-ко-многим" междуобъектами так, что при изменении состояния одного объекта всезависящие от него объекты уведомляются и обновляются автоматически.
• Паттерн State позволяет объекту изменять свое поведение в зависимостиот внутреннего состояния. Создается впечатление, что объект изменилсвой класс. Паттерн State является объектно-ориентированнойреализацией конечного автомата.
• Если поведение системы настраивается согласно одному из некоторогомножества алгоритму, то применение паттерна Strategy переноситсемейство алгоритмов в отдельную иерархию классов, что позволяетзаменять один алгоритм другим в ходе выполнения программы. Крометого, такую систему проще расширять и поддерживать.
• Паттерн Template Method определяет основу алгоритма и позволяетподклассам изменить некоторые шаги этого алгоритма без изменения егообщей структуры.
• Паттерн Visitor определяет операцию, выполняемую на каждом элементеиз некоторой структуры без изменения классов этих объектов.
Шаблоны поведения
http://www.slideshare.net/IgorShkulipa 83
var Singleton = (function () {
var instance;
function createInstance() {
return {
name: "Ivan",
surname: "Ivanov",
alertme: function () {
alert(this.name+" "+this.surname);}
}
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
var instance1 = Singleton.getInstance();
instance1.name= "Petr";
var instance2 = Singleton.getInstance();
alert(instance1 === instance2);
instance1.alertme();
instance2.alertme();
Шаблон проектирования Singleton
http://www.slideshare.net/IgorShkulipa 84
Применяется, когда нужен только один экземпляр класса.Например для хранения глобальной конфигурации системы, дляведения логов, связи с базой данных и т.д.
Основное преимущество перед глобальными переменными втом, что экземпляр класса создается не при инициализациипрограммы, а по первому требованию.
Применение Singleton