SlideShare a Scribd company logo
1 of 47
JavaScript OOP. How is it possible?
Table of contents 
Introduction 
1. JavaScript data types 
1.1. String 
1.2. Number 
1.3. Boolean 
1.4. Object 
1.5. Array 
1.6. null 
1.7. undefined 
1.8. Преобразование типов
Table of contents 
2. OOP in JavaScript 
2.1. Object 
2.1.1. Свойства объектов 
2.1.2. Геттеры и сеттеры 
2.1.3. Методы объекта 
2.1.4. Что такое this? Магия в действии 
2.1.5. Литеральный синтаксис определения объекта 
2.1.6. Наследование объектов 
2.2. Class 
2.2.1. Классы. Наследование 
2.2.2. Классы и прототипы. Наследование
Introduction 
Изначально JavaScript позиционируется как объектно- 
ориентированный язык. Это утверждение вызывает споры среди 
разработчиков. Основные контраргументы: 
• Где классы? 
• Где наследование? 
• И вообще WTF?
Внешне JavaScript (ECMAScript) выглядит как Java, но фактически это 
совершенно другой язык, прототипом которого является язык Self 
(http://selflanguage.org/). Это обстоятельство делает язык очень 
простым и сравнительно мощным благодаря своим особенностям. 
Одна из таких особенностей – это реализация прототипного 
наследования. Этот простой концепт является гибким и мощным. Он 
позволяет сделать наследование и поведение сущностями первого 
класса, также как и функции являются объектами первого класса в 
функциональных языках (включая JavaScript).
1. JavaScript data types 
В JavaScript есть три основных типа данных, два составных типа 
данных и два специальных типа данных. Итого 7 типов данных. 
Мощно? – Мощно! 
Основные типы данных (базовые): 
• String 
• Number 
• Boolean
Составные типы данных (ссылочные): 
• Object 
• Array 
Специальные типы данных: 
• null 
• Undefined 
А где же классы? Пичалька…
1.1 String 
Строковое значение представляет собой цепочку, состоящую из нуля 
или более знаков Unicode (букв, цифр или знаков пунктуации). 
Строковый тип данных используется для представления текста в 
JavaScript. Для включения в скрипты строковых литералов, их 
необходимо заключить в одинарные или двойные кавычки. В 
строках, заключенных в одинарные кавычки, можно использовать 
двойные кавычки, а в строках, заключенных в двойные кавычки, 
можно использовать одинарные кавычки. Ниже представлены 
примеры строк: 
"String!" 
'"String!" String.' 
"12345" 
's'
Обратите внимание, что JavaScript не имеет типа для представления 
одиночного символа. Для представления отдельного символа в 
JavaScript используется строка, которая состоит только из одного 
символа. Строка, не содержащая знаков ("") называется пустой 
строкой (или строкой нулевой длины). 
Для представления знаков, которые невозможно ввести без 
преобразования, в JavaScript предусмотрены escape- 
последовательности, включаемые в строки. 
Например, t задает символ табуляции.
1.2 Number 
• В JavaScript, нет различия между целым числом и числом с плавающей 
запятой; число JavaScript может быть и тем, и тем (по сути, JavaScript 
представляет все числа в качестве значения с плавающей запятой). 
• Целочисленные значения могут быть положительными целыми числами, 
отрицательным целыми числами и 0. В качестве основы представления этих 
чисел можно использовать 10 (десятичное представление), 16 
(шестнадцатеричное представление) и 8 (восьмеричное представление). 
Большинство чисел в JavaScript записываются в десятичном представлении. 
• Все шестнадцатеричные ("hex") целые числа содержат префикс "0x" (ноль и 
x|X). В их состав могут входить только цифры от 0 до 9 и буквы от A до F (в 
верхнем или нижнем регистре). Буквы A-F используются для представления 
десятичных чисел от 10 до 15. То есть шестнадцатеричное число 0xF 
эквивалентно десятичному числу 15, а 0x10 эквивалентно числу 16. 
• Все восьмеричные целые числа содержат префикс "0" (ноль). В их состав 
могут входить только цифры от 0 до 7. Число, которое начинается с цифры "0" 
и содержит цифры "8" и (или) "9", интерпретируется как десятичное.
• Восьмеричные и шестнадцатеричные числа могут быть отрицательными, 
однако они не могут содержать дробную часть и их невозможно записать в 
научной (экспоненциальной) нотации. 
– Кроме того, JavaScript содержит числа со следующими специальными 
значениями: 
– NaN (не число). Используется при выполнении математической операции 
над недопустимыми данными, такими как строки или неопределенное 
значение 
– Положительная бесконечность. Используется, если положительное число 
слишком велико и не может быть представлено в JavaScript 
– Отрицательная бесконечность. Используется, если отрицательное число 
слишком велико и не может быть представлено в JavaScript 
– Положительный и отрицательный 0. JavaScript различает положительный и 
отрицательный ноль.
1.3 Boolean 
В то время как строковые и числовые типы данных могут принимать 
практическое неограниченное число различных значений, 
логический тип данных может принимать только два значения. Это 
литералы true и false. Логическое значение является значением 
истинности: оно определяет, является ли условие истинным или нет. 
Результат сравнения в скриптах всегда будет иметь тип логического 
значения. Пример: (x == 124)
1.4 Object 
• Объекты JavaScript представляют собой коллекции свойств и методов (Аналог 
Map в Java). Методом называется функция, являющаяся членом объекта. 
Свойство представляет собой значение или набор значений (в виде массива 
или объекта), который является членом объекта. JavaScript поддерживает 
четыре типа объектов: встроенные объекты, создаваемые объекты, 
предоставляемые основным узлом объекты (например, window и document в 
браузере) и объекты ActiveX. 
• Все объекты в JavaScript поддерживают свойства и методы "expando", а также 
свойства, которые могут быть добавлены и удалены во время выполнения. 
Эти свойства и методы могут иметь любые имена, включая числа. Если имя 
свойства или методы является простым идентификатором, то оно может быть 
указано через точку после имени метода, например:
var myObj = new Object(); 
myObj.name = "Fred"; 
myObj.age = 42; 
myObj.getAge = 
function () { 
return this.age; 
}; 
document.write(myObj.name); 
document.write("<br/>"); 
document.write(myObj.age); 
document.write("<br/>"); 
document.write(myObj.getAge()); 
// Output: 
// Fred 
// 42 
// 42 
Можно ознакомиться с этим в примере example-001.html
• Если имя свойства или метода не является простым идентификатором или 
неизвестно в момент написания скрипта, то можно использовать выражение 
в квадратных скобках для обозначения свойства. Перед добавлением к 
объекту имена всех свойств "expando" в JavaScript преобразуются в строки. 
var myObj = new Object(); 
// Add two expando properties that cannot be written in the 
// object.property syntax. 
// The first contains invalid characters (spaces), so must be 
// written inside square brackets. 
myObj["not a valid identifier"] = "This is the property value"; 
// The second expando name is a number, so it also must 
// be placed inside square brackets 
myObj[100] = "100";
Получить доступ к таким свойствам можно только используя их строковые 
значения или обход по for each. 
Для создания объектов можно использовать также, так называемую JavaScript 
Object Notation (JSON). 
Например: 
var pasta = {grain: "wheat", width: 0.5, shape: "round"};
1.5 Array 
• В JavaScript объекты и массивы обрабатываются практически 
одинаково, поскольку массивы – это специальный тип объекта. 
Они оба могут содержать свойства и методы. 
• В отличие от объектов, массивы имеют свойство length. При 
присвоении значения к элементу массива, индекс которого 
больше длины (например, myArray[100] = "hello"), свойство length 
автоматически увеличивается до новой длины. Аналогично, при 
уменьшении значения свойства length, любой элемент с индексом 
за пределами длины массива удаляется.
// An array with three elements 
var myArray = new Array(3); 
// Add some data 
myArray[0] = "Hello"; 
myArray[1] = 42; 
myArray[2] = new Date(2000, 1, 1); 
document.write("original length is: " + myArray.length); 
document.write("<br/>"); 
// Add some expand properties 
myArray.expando = "JavaScript!"; 
myArray["another Expando"] = "Windows"; 
// This will still display 3, since the two expando properties 
// don't affect the length. 
document.write("new length is : " + myArray.length); 
// Output: 
// original length is: 3 
// new length is : 3
1.6 null 
Тип данных null имеет только одно значение в JavaScript: значение 
null. Ключевое слово null невозможно использовать в качестве 
имени функции или переменной. 
Переменная, которая содержит null, не содержит допустимых 
Number, String, Boolean, Array или Object. Можно стереть 
содержимое переменной (не удаляя переменную), присваивая ей 
значение null. 
Обратите внимание, что в JavaScript значение null – не то же самое, 
что 0 (как в C и C++). Кроме того, оператор typeof в JavaScript 
определяет значения null как значения типа Object, а не типа null. 
Такое поведение, которое может запутать разработчиков, 
используется в целях обратной совместимости.
1.7 undefined 
Значение undefined возвращается при использовании свойства 
объекта, которое не существует, или переменной, которая была 
объявлена, но так и не получила значения. 
Можно проверить, существует ли переменная, сравнивая ее с 
undefined, однако можно проверить, является ли ее тип undefined, 
сравнивая тип переменной со строкой "undefined". В следующем 
примере показано, как определить, была ли объявлена переменная 
x:
var x; 
// This method works. 
if (x == undefined) { 
document.write("comparing x to undefined <br/>"); 
} 
// This method works. 
if (x == null) { 
document.write("comparing x to null <br/>"); 
} 
// This method doesn't work - you must check for the string "undefined". 
if (typeof(x) == undefined) { 
document.write("comparing the type of x to undefined <br/>"); 
} 
// This method does work. 
if (typeof(x) == "undefined") { 
document.write("comparing the type of x to the string 'undefined'"); 
} 
// Output: 
// comparing x to undefined 
// comparing x to null 
// comparing the type of x to the string 'undefined' 
undefined довольно странный 
зверек, условно говоря, оно 
обозначает что "данных нет". 
Не null, а данных нет. 
Понимайте как хотите.
1.8 Преобразование типов 
Преобразование типа можно явным образом сделать через его 
название: 
var test = Boolean("something") // true
2. OOP in JavaScript. 2.1 Object 
Объект в JavaScript – это просто коллекция пар ключ-значение (и немного 
внутренней магии). Однако, в JavaScript нет концепции класса. К примеру, 
объект с свойствами {name: Eugene, age: 16} не является экземпляром какого- 
либо класса или класса Object. И Object, и Eugene являются экземплярами самих 
себя. Они определяются непосредственно собственным поведением. Тут нет 
слоя мета-данных (т.е. классов), которые говорили бы этим объектам как нужно 
себя вести. 
Сразу возникает вопрос: «WTF?», особенно если вы пришли из мира 
классических объектно-ориентированных языков (таких как Java или C#). «Но 
если каждый объект обладает собственным поведением (вместо того чтобы 
наследовать его от общего класса), то если у меня 100 объектов, то им 
соответствует 100 разных методов? Разве это не опасно? А как мне узнать, что, 
например, объект действительно является Array-ем?»
Чтобы ответить на все эти вопросы необходимо забыть о классическом ОО- 
подходе и начать всё с нуля. Оно того стоит. 
Модель прототипного ОО приносит несколько новых динамичных и 
экспрессивных путей решения старых проблем. В ней также представлены 
мощные модели расширения и повторного использования кода (а это и 
интересует людей, которые говорят об объектно-ориентированном 
программировании). Однако, эта модель даёт меньше гарантий. Например, 
нельзя полагаться, что объект x всегда будет иметь один и тот же набор свойств. 
Объект в JavaScript создаётся с помощью функции Object.create. Эта функция из 
родителя и опционального набора свойств создаёт новую сущность. 
Так как объекты — это просто пары уникальных ключей с соответствующими 
значениями – такие пары называются свойства. К примеру, вы хотите описать 
несколько аспектов своего старого друга (назовём его Юджин, он же Eugene), 
таких как возраст, имя и пол. Итак, академический способ:
var Eugene = Object.create(null) 
Классика ООП: 
var Eugene = new Object() 
Упрощенная нотация: 
var Eugene = {}
2.1.1 Свойства объектов 
Свойства в JavaScript являются динамическими. Это означает, что мы их можем 
создавать или удалять в любое время. Свойства уникальны в том смысле, что 
ключ свойства внутри объекта соответствует ровно одному значению. 
В Javascript есть функция, позволяющая создат свойство объякта, правильно: 
Object.defineProperty. В качестве аргументов она использует объект, имя 
свойства для создания и дескриптор, описывающий семантику свойства. 
Например: 
Object.defineProperty(Eugene, 'name', { value: 'Eugene' , writable: true , 
configurable: true , enumerable: true }) 
Или упрощенно: 
Eugene.name = 'Eugene' 
Eugene['name'] = 'Eugene'
Для удаления свойства из объекта в JavaSCript предусмотрен оператор delete. К 
примеру, если вы хотите удалить свойство gender из нашего объекта mikhail: 
delete Eugene [‘name’] 
// => true 
Eugene [‘name’] 
// => undefined
2.1.2 Геттеры и сеттеры 
Getter-ы и setter-ы обычно используются в классических объектно-ориентированных языках для 
обеспечения инкапсуляции. Геттеры и сеттеры в JavaScript позволяет обеспечить proxy для 
запросов на чтение и запись свойств. Поскольку понятие области видимости в JavaScript нет, то и 
задач инкапсуляции геттеры/сеттеры не решают. Пример классического определения 
Геттера/Сеттера: 
Object.defineProperty(Illya, 'name', { 
configurable: true, 
enumerable: true, 
get: function () { 
return "My Name is: " + this._name; 
}, 
set: function (value) { 
this._name = value; 
} 
});
2.1.3 Методы объекта 
Описание действий, которые можно делать с объектом делается в JavaScript очень просто. 
Почему? Да, потому, что в JavaScript нет разницы между манипулированием такими вещами, 
как Function, Number, Object. Всё делается одинаково. Любой метод является просто свойством 
текущего объекта типа Function, которое создается динамически и может быть использовано в 
контексте этого объекта. 
Пример: 
var Eugene = { name: "Eugene" }; 
Eugene.getName = function () { 
return this.name; 
}; 
Eugene.setName = function (value) { 
this.name = value; 
};
2.1.4 Что такое this? Магия в действии 
this – это одна из самых важных переменных в JavaScript, она хранит в себе 
ссылку на объект, которому принадлежит исполняющаяся функция. Это не 
обязательно означает, что this всегда равно объекту, в котором функция 
хранится. Нет, JavaScript не настолько эгоистичен. 
Функции являются generic-ами. Т.е. в JavaScript переменная this определяет 
динамическую ссылку, которая разрешается в момент исполнения функции. 
Процесс динамического разрешения this обеспечивает невероятно мощный 
механизм для динамизации объектной ориентированности JavaScript и 
компенсирует отсутствие строгого соответствия заданным структурам (т.е. 
классам). Это означает, что можно применить функцию к любому объекту, 
который отвечает требованиям запуска, независимо от того, как устроен объект
Существует четыре различных способа разрешения this в функции, зависящие от 
того, как функция вызывается: 
• непосредственно, когда функция вызывается сама по себе, без объектного 
контекста. Например: someFunction1(). В этом слечае this это глобальный 
контекст (в браузере это объект window) 
• как метод, например: Eugene.getName(), в таком случае this будет 
тождественно объекту Eugene. 
• явно применяется. В JavaScript любая функция может быть вызвана в 
контексте некоторого объекта используя методы call или apply. Рассмотрим 
пример:
function getObjectQName(parameter1) { 
var result = "My Name is: " + this.name; 
if (parameter1 != null) { 
result += ", and parameter1 is: " + parameter1; 
} 
return result; 
} 
getObjectQName.call(Eugene, "PAR-1"); // this === Eugene 
getObjectQName.call(Illya, "PARAMETER-1"); // this === Illya 
// Bind example 
Eugene.illyaNameFnc = getObjectQName.bind(Illya); 
writeLog(Eugene.illyaNameFnc("PAR-1")); // this === Illya
• как конструктор. Этот контекст рассмотрим позднее.
2.1.5 Литеральный синтаксис определения 
объекта 
Простой способ создать объект заключается в использовании литерального 
синтаксиса JavaScript. Литеральный объект определяет новый объект, родитель 
которого Object.prototype. Пример этого синтаксиса приведен ниже: 
var Eugene = { 
_name: "Eugene", 
_age: 18, 
get name() { return this._name; }, 
set name(value) { this._name = value; }, 
getAge: function(){ return this._age; } 
};
2.1.6 Наследование объектов? 
• Наследование в JavaScript осуществляется через клонирование поведения 
объекта и расширение его специализированным поведением. Объект, 
поведение которого клонируют, называется прототипом. 
• Прототип – это обычный объект, который делится своим поведением с 
другими объектами – в этом случае он выступает в качестве родителя. 
• Концепт клонирования поведения не означает, что вы будете иметь две 
различные копии одной и той же функции или данных. На самом деле 
JavaScript реализует наследование через делегирование, т.е. все свойства 
хранятся в родителе, а доступ к ним расширен через ребёнка. 
• Как упоминалось ранее, родитель (или [[Prototype]]) объекта определяется 
вызовом Object.create с первым аргументом, ссылающимся на объект- 
родитель. Рассмотрим пример:
var Person = { 
_name: "Unknown", 
_age: 0, 
get name() { return this._name; }, 
set name(value) { this._name = value; }, 
getLocalName: function(){ return "Person: " + this._name; }, 
getAge: function(){ return this._age; } 
}; 
writeLog(Person.name); 
writeLog(Person.getAge()); 
var Eugene = Object.create(Person); 
Eugene.name = "Eugene"; 
Eugene._age = 18; 
writeLog(Eugene.name); 
writeLog(Eugene.getAge()); 
writeLog(""); 
writeLog("Dynamically overloading getLocalName() object method"); 
writeLog(Eugene.getLocalName()); 
Eugene.getLocalName = function () { return "From Eugene: " + this._name; }; 
writeLog(Eugene.getLocalName()); 
delete Eugene.getLocalName; 
writeLog(Eugene.getLocalName());
JavaScript реализует делегирование доступа к свойствам, т.е. свойство ищется 
через всех родителей объекта. 
Эта цепь родителей определяется скрытым слотом в каждом объекте, который 
называется [[Prototype]]. Вы не можете изменить его непосредственно, 
существует только один способ задать ему значение – при создании нового 
объекта. 
Когда свойство запрашивается из объекта, движок сначала пытается получить 
свойство из целевого объекта. Если свойство не найдено, то рассматривается 
непосредственный родитель объекта, затем родитель родителя и т.д. 
Это означает, что мы можем изменить поведение прототипа в середине 
программы, то автоматически изменится поведение всех объектов, которые 
были от него унаследованы.
2.2 Class. 2.2.1 Классы 
Итак, самая большая магия. В JavaScript классы – это функции! WTF? 
Любая функция, кроме некоторых встроенных, может быть инициализирована 
как объект. Для этого ее нужно вызвать через директиву new. Итак: 
RiaShamans.JSExamples.Person = function (name, age, mass) { 
this.name = name; 
this.age = age; 
this.mass = mass; 
}; 
var Eugene = new ("Eugene", 18, 65);
Во время работы функции, вызванной директивой new, новосоздаваемый 
объект доступен как this, так что можно проставить любые свойства. 
Класс объекта определяется функцией, которая его создала. Для проверки 
принадлежности классу есть оператор instanceof: 
var Eugene = new RiaShamans.JSExamples.Person("Eugene", 18, 65); 
writeLog(Eugene instanceof RiaShamans.JSExamples.Person);
2.2.2 Пространства имен и пакеты 
Поскольку классы и объекты реализуются в виде переменных (переменных- 
функций и переменных-объектов), то пространства имен могут быть 
реализованы в виде полей-переменных Объектов. Например: 
if (typeof(RiaShamans) == "undefined") RiaShamans = {}; 
if (typeof(RiaShamans.JSExamples) == "undefined") RiaShamans.JSExamples = {}; 
Таким образом создан пакет RiaShamans.JSExamples, который может 
использоваться для определения классов или объектов. Например:
if (typeof(RiaShamans) == "undefined") RiaShamans = {}; 
if (typeof(RiaShamans.JSExamples) == "undefined") RiaShamans.JSExamples = {}; 
/** 
* Class defines Person Entity 
* 
* @class {RiaShamans.JSExamples.Person} 
* @param name 
* @param age 
* @param mass 
* @returns {RiaShamans.JSExamples.Person} 
*/ 
RiaShamans.JSExamples.Person = function (name, age, mass) { 
};
2.2.3 Классы и прототипы. Наследование 
В javascript базовое наследование основано не на классах. То есть, нет такого, что 
классы наследуют друг от друга, а объект класса-потомка получает общие 
свойства. Вместо этого объекты наследуют от объектов без всяких классов. 
Наследование на классах можно построить(эмулировать), опираясь на базовое 
наследование javascript. 
Реализуется наследование через неявную(внутреннюю) ссылку одного объекта 
на другой, который называется его прототипом и в спецификации обозначается 
[[prototype]]. Это свойство обычно скрыто от программиста. Также существует 
свойство с похожим названием prototype (без квадратных скобок) – оно 
вспомогательное и указывает, откуда брать прототип при создании объекта. 
Когда вы ставите функции Person свойство Person.prototype = XXX – вы этим 
декларируете: "все новые объекты класса Person будут иметь прототип XXX". 
Рассмотрим пример:
if (typeof(RiaShamans) == "undefined") RiaShamans = {}; 
if (typeof(RiaShamans.JSExamples) == "undefined") RiaShamans.JSExamples = {}; 
/** 
* Class defines Person Entity 
* 
* @class {RiaShamans.JSExamples.Person} 
* @param name 
* @param age 
* @param mass 
* @returns {RiaShamans.JSExamples.Person} 
*/ 
RiaShamans.JSExamples.Person = function (name, age, mass) { 
this.initPerson(name, age, mass); 
}; 
RiaShamans.JSExamples.Person.prototype.constructor = RiaShamans.JSExamples.Person; 
/** 
* Initialize person Data 
* 
* @param name 
* @param age 
* @param mass 
*/ 
RiaShamans.JSExamples.Person.prototype.initPerson = function(name, age, mass){ 
this.name = name; 
this.age = age; 
this.mass = mass; 
};
/** 
* Returns Person name 
* 
* @returns {String} 
*/ 
RiaShamans.JSExamples.Person.prototype.getName = function(){ 
return this.name; 
}; 
/** 
* Returns person Age 
* 
* @returns Number 
*/ 
RiaShamans.JSExamples.Person.prototype.getAge = function(){ 
return this.age; 
}; 
/** 
* Class defines gendered Person Entity 
* 
* @class {RiaShamans.JSExamples.GenderPerson} 
* @augments {RiaShamans.JSExamples.Person} 
* @lends {RiaShamans.JSExamples.Person.prototype} 
*/ 
RiaShamans.JSExamples.GenderPerson = function (name, age, mass) { 
// Inherit parent constructor 
RiaShamans.JSExamples.GenderPerson.superclass.constructor.call(this, name, age, mass); // this is equivalent of 
RiaShamans.JSExamples.Person.call(this, name, age, mass); 
this.gender = "UNKNOWN"; 
};
// Implement Inheritance 
var GenderPersonPrototype = function(){}; 
GenderPersonPrototype.prototype = RiaShamans.JSExamples.Person.prototype; // Create prototype without parameters. We can't Instantiate Parent 
without proper data in some cases. 
RiaShamans.JSExamples.GenderPerson.prototype = new GenderPersonPrototype(); // Add all parent prototype data to Child class 
RiaShamans.JSExamples.GenderPerson.prototype.constructor = RiaShamans.JSExamples.GenderPerson; // Set constructor 
RiaShamans.JSExamples.GenderPerson.superclass = RiaShamans.JSExamples.Person.prototype; // Set superclass for Child 
/** 
* Returns Gender 
* 
* @returns {String} 
*/ 
RiaShamans.JSExamples.GenderPerson.prototype.getGender = function(){ 
return this.gender; 
}; 
/** 
* Set Gender for a Person 
* 
* @param value 
*/ 
RiaShamans.JSExamples.GenderPerson.prototype.setGender = function(value){ 
this.gender = value; 
};
2.2.4 Статические методы 
Поскольку классы в JavaScript (они же функции), это в свою очередь объекты, то 
для них можно определять поля в виде функций. Такая функция будет доступна 
без инициализации объекта класса и в контексте самого класса, являясь 
аналогом статического метода в классическом ООП. Рассмотрим пример:
/** 
* Factory class. Example of static methods 
* 
* @class {RiaShamans.JSExamples.PersonFactory} 
* @lends {RiaShamans.JSExamples.PersonFactory.prototype} 
*/ 
RiaShamans.JSExamples.PersonFactory = function(){ 
}; 
/** 
* Factory method. creates person and returns its instance 
* 
* @returns {RiaShamans.JSExamples.Person} 
*/ 
RiaShamans.JSExamples.PersonFactory.createPerson = function(name, age, mass){ 
var result = new RiaShamans.JSExamples.Person(name, age, mass); 
return result; 
};

More Related Content

What's hot

Глава1: Обзор технологии Java
Глава1: Обзор технологии JavaГлава1: Обзор технологии Java
Глава1: Обзор технологии Javametaform
 
Java. Generic - шаблонные типы.
Java.  Generic - шаблонные типы.Java.  Generic - шаблонные типы.
Java. Generic - шаблонные типы.Unguryan Vitaliy
 
ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)
ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)
ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)ScalaNsk
 
Погружение в Dart
Погружение в DartПогружение в Dart
Погружение в DartSergey Penkovsky
 
Базовые операторы Java
Базовые операторы JavaБазовые операторы Java
Базовые операторы Javametaform
 
C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.Igor Shkulipa
 
Рефлексия в java
Рефлексия в javaРефлексия в java
Рефлексия в javaUnguryan Vitaliy
 
Алгоритмы поиска и сортировки
Алгоритмы  поиска и сортировкиАлгоритмы  поиска и сортировки
Алгоритмы поиска и сортировкиUnguryan Vitaliy
 
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)ScalaNsk
 
Scala and LiftWeb presentation (Russian)
Scala and LiftWeb presentation (Russian)Scala and LiftWeb presentation (Russian)
Scala and LiftWeb presentation (Russian)Dmitry Stropalov
 
Java. Cистемы счислния, битовые операции
Java. Cистемы счислния, битовые операцииJava. Cистемы счислния, битовые операции
Java. Cистемы счислния, битовые операцииUnguryan Vitaliy
 
Исключения и ошибки
Исключения и ошибкиИсключения и ошибки
Исключения и ошибкиUnguryan Vitaliy
 

What's hot (15)

Глава1: Обзор технологии Java
Глава1: Обзор технологии JavaГлава1: Обзор технологии Java
Глава1: Обзор технологии Java
 
Java. Generic - шаблонные типы.
Java.  Generic - шаблонные типы.Java.  Generic - шаблонные типы.
Java. Generic - шаблонные типы.
 
ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)
ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)
ООП в Scala: выход из застоя (ScalaNsk meeting #5, 22.11.2013)
 
Погружение в Dart
Погружение в DartПогружение в Dart
Погружение в Dart
 
java 8
java 8java 8
java 8
 
Базовые операторы Java
Базовые операторы JavaБазовые операторы Java
Базовые операторы Java
 
ООП_лекция_11
ООП_лекция_11ООП_лекция_11
ООП_лекция_11
 
Regular Expressions
Regular ExpressionsRegular Expressions
Regular Expressions
 
C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.
 
Рефлексия в java
Рефлексия в javaРефлексия в java
Рефлексия в java
 
Алгоритмы поиска и сортировки
Алгоритмы  поиска и сортировкиАлгоритмы  поиска и сортировки
Алгоритмы поиска и сортировки
 
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
 
Scala and LiftWeb presentation (Russian)
Scala and LiftWeb presentation (Russian)Scala and LiftWeb presentation (Russian)
Scala and LiftWeb presentation (Russian)
 
Java. Cистемы счислния, битовые операции
Java. Cистемы счислния, битовые операцииJava. Cистемы счислния, битовые операции
Java. Cистемы счислния, битовые операции
 
Исключения и ошибки
Исключения и ошибкиИсключения и ошибки
Исключения и ошибки
 

Similar to OOP in JavaScript - Presentation by Eugene Kalosha

Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?Vasil Remeniuk
 
JavaScript. Basics (in russian)
JavaScript. Basics (in russian)JavaScript. Basics (in russian)
JavaScript. Basics (in russian)Mikhail Davydov
 
Msu.Center.Lectures.J01 Introducing Java
Msu.Center.Lectures.J01 Introducing JavaMsu.Center.Lectures.J01 Introducing Java
Msu.Center.Lectures.J01 Introducing Javaolegol
 
Статический анализ и регулярные выражения
Статический анализ и регулярные выраженияСтатический анализ и регулярные выражения
Статический анализ и регулярные выраженияTatyanazaxarova
 
Pavel Rumantsev - Java Script
Pavel Rumantsev - Java ScriptPavel Rumantsev - Java Script
Pavel Rumantsev - Java Scriptbeloslab
 
введение в Javascript
введение в Javascriptвведение в Javascript
введение в Javascriptinqubick
 
Типы данных
Типы данныхТипы данных
Типы данныхMonsterXX
 
Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)Ontico
 
Groovy jug-moscow-part 1
Groovy jug-moscow-part 1Groovy jug-moscow-part 1
Groovy jug-moscow-part 1Evgeny Borisov
 

Similar to OOP in JavaScript - Presentation by Eugene Kalosha (20)

Javascript 1
Javascript 1Javascript 1
Javascript 1
 
Underscore js
Underscore jsUnderscore js
Underscore js
 
Step 3.2
Step 3.2Step 3.2
Step 3.2
 
Обзор Ruby
Обзор RubyОбзор Ruby
Обзор Ruby
 
Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?
 
JavaScript. Basics (in russian)
JavaScript. Basics (in russian)JavaScript. Basics (in russian)
JavaScript. Basics (in russian)
 
Msu.Center.Lectures.J01 Introducing Java
Msu.Center.Lectures.J01 Introducing JavaMsu.Center.Lectures.J01 Introducing Java
Msu.Center.Lectures.J01 Introducing Java
 
Module 5 1
Module 5 1Module 5 1
Module 5 1
 
Scala lecture #4
Scala lecture #4Scala lecture #4
Scala lecture #4
 
Статический анализ и регулярные выражения
Статический анализ и регулярные выраженияСтатический анализ и регулярные выражения
Статический анализ и регулярные выражения
 
Pavel Rumantsev - Java Script
Pavel Rumantsev - Java ScriptPavel Rumantsev - Java Script
Pavel Rumantsev - Java Script
 
введение в Javascript
введение в Javascriptвведение в Javascript
введение в Javascript
 
Scala #4
Scala #4Scala #4
Scala #4
 
Типы данных
Типы данныхТипы данных
Типы данных
 
Lec 4
Lec 4Lec 4
Lec 4
 
Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)
 
87
8787
87
 
course js day 2
course js day 2course js day 2
course js day 2
 
Groovy jug-moscow-part 1
Groovy jug-moscow-part 1Groovy jug-moscow-part 1
Groovy jug-moscow-part 1
 
Bytecode
BytecodeBytecode
Bytecode
 

OOP in JavaScript - Presentation by Eugene Kalosha

  • 1. JavaScript OOP. How is it possible?
  • 2. Table of contents Introduction 1. JavaScript data types 1.1. String 1.2. Number 1.3. Boolean 1.4. Object 1.5. Array 1.6. null 1.7. undefined 1.8. Преобразование типов
  • 3. Table of contents 2. OOP in JavaScript 2.1. Object 2.1.1. Свойства объектов 2.1.2. Геттеры и сеттеры 2.1.3. Методы объекта 2.1.4. Что такое this? Магия в действии 2.1.5. Литеральный синтаксис определения объекта 2.1.6. Наследование объектов 2.2. Class 2.2.1. Классы. Наследование 2.2.2. Классы и прототипы. Наследование
  • 4. Introduction Изначально JavaScript позиционируется как объектно- ориентированный язык. Это утверждение вызывает споры среди разработчиков. Основные контраргументы: • Где классы? • Где наследование? • И вообще WTF?
  • 5. Внешне JavaScript (ECMAScript) выглядит как Java, но фактически это совершенно другой язык, прототипом которого является язык Self (http://selflanguage.org/). Это обстоятельство делает язык очень простым и сравнительно мощным благодаря своим особенностям. Одна из таких особенностей – это реализация прототипного наследования. Этот простой концепт является гибким и мощным. Он позволяет сделать наследование и поведение сущностями первого класса, также как и функции являются объектами первого класса в функциональных языках (включая JavaScript).
  • 6. 1. JavaScript data types В JavaScript есть три основных типа данных, два составных типа данных и два специальных типа данных. Итого 7 типов данных. Мощно? – Мощно! Основные типы данных (базовые): • String • Number • Boolean
  • 7. Составные типы данных (ссылочные): • Object • Array Специальные типы данных: • null • Undefined А где же классы? Пичалька…
  • 8. 1.1 String Строковое значение представляет собой цепочку, состоящую из нуля или более знаков Unicode (букв, цифр или знаков пунктуации). Строковый тип данных используется для представления текста в JavaScript. Для включения в скрипты строковых литералов, их необходимо заключить в одинарные или двойные кавычки. В строках, заключенных в одинарные кавычки, можно использовать двойные кавычки, а в строках, заключенных в двойные кавычки, можно использовать одинарные кавычки. Ниже представлены примеры строк: "String!" '"String!" String.' "12345" 's'
  • 9. Обратите внимание, что JavaScript не имеет типа для представления одиночного символа. Для представления отдельного символа в JavaScript используется строка, которая состоит только из одного символа. Строка, не содержащая знаков ("") называется пустой строкой (или строкой нулевой длины). Для представления знаков, которые невозможно ввести без преобразования, в JavaScript предусмотрены escape- последовательности, включаемые в строки. Например, t задает символ табуляции.
  • 10. 1.2 Number • В JavaScript, нет различия между целым числом и числом с плавающей запятой; число JavaScript может быть и тем, и тем (по сути, JavaScript представляет все числа в качестве значения с плавающей запятой). • Целочисленные значения могут быть положительными целыми числами, отрицательным целыми числами и 0. В качестве основы представления этих чисел можно использовать 10 (десятичное представление), 16 (шестнадцатеричное представление) и 8 (восьмеричное представление). Большинство чисел в JavaScript записываются в десятичном представлении. • Все шестнадцатеричные ("hex") целые числа содержат префикс "0x" (ноль и x|X). В их состав могут входить только цифры от 0 до 9 и буквы от A до F (в верхнем или нижнем регистре). Буквы A-F используются для представления десятичных чисел от 10 до 15. То есть шестнадцатеричное число 0xF эквивалентно десятичному числу 15, а 0x10 эквивалентно числу 16. • Все восьмеричные целые числа содержат префикс "0" (ноль). В их состав могут входить только цифры от 0 до 7. Число, которое начинается с цифры "0" и содержит цифры "8" и (или) "9", интерпретируется как десятичное.
  • 11. • Восьмеричные и шестнадцатеричные числа могут быть отрицательными, однако они не могут содержать дробную часть и их невозможно записать в научной (экспоненциальной) нотации. – Кроме того, JavaScript содержит числа со следующими специальными значениями: – NaN (не число). Используется при выполнении математической операции над недопустимыми данными, такими как строки или неопределенное значение – Положительная бесконечность. Используется, если положительное число слишком велико и не может быть представлено в JavaScript – Отрицательная бесконечность. Используется, если отрицательное число слишком велико и не может быть представлено в JavaScript – Положительный и отрицательный 0. JavaScript различает положительный и отрицательный ноль.
  • 12. 1.3 Boolean В то время как строковые и числовые типы данных могут принимать практическое неограниченное число различных значений, логический тип данных может принимать только два значения. Это литералы true и false. Логическое значение является значением истинности: оно определяет, является ли условие истинным или нет. Результат сравнения в скриптах всегда будет иметь тип логического значения. Пример: (x == 124)
  • 13. 1.4 Object • Объекты JavaScript представляют собой коллекции свойств и методов (Аналог Map в Java). Методом называется функция, являющаяся членом объекта. Свойство представляет собой значение или набор значений (в виде массива или объекта), который является членом объекта. JavaScript поддерживает четыре типа объектов: встроенные объекты, создаваемые объекты, предоставляемые основным узлом объекты (например, window и document в браузере) и объекты ActiveX. • Все объекты в JavaScript поддерживают свойства и методы "expando", а также свойства, которые могут быть добавлены и удалены во время выполнения. Эти свойства и методы могут иметь любые имена, включая числа. Если имя свойства или методы является простым идентификатором, то оно может быть указано через точку после имени метода, например:
  • 14. var myObj = new Object(); myObj.name = "Fred"; myObj.age = 42; myObj.getAge = function () { return this.age; }; document.write(myObj.name); document.write("<br/>"); document.write(myObj.age); document.write("<br/>"); document.write(myObj.getAge()); // Output: // Fred // 42 // 42 Можно ознакомиться с этим в примере example-001.html
  • 15. • Если имя свойства или метода не является простым идентификатором или неизвестно в момент написания скрипта, то можно использовать выражение в квадратных скобках для обозначения свойства. Перед добавлением к объекту имена всех свойств "expando" в JavaScript преобразуются в строки. var myObj = new Object(); // Add two expando properties that cannot be written in the // object.property syntax. // The first contains invalid characters (spaces), so must be // written inside square brackets. myObj["not a valid identifier"] = "This is the property value"; // The second expando name is a number, so it also must // be placed inside square brackets myObj[100] = "100";
  • 16. Получить доступ к таким свойствам можно только используя их строковые значения или обход по for each. Для создания объектов можно использовать также, так называемую JavaScript Object Notation (JSON). Например: var pasta = {grain: "wheat", width: 0.5, shape: "round"};
  • 17. 1.5 Array • В JavaScript объекты и массивы обрабатываются практически одинаково, поскольку массивы – это специальный тип объекта. Они оба могут содержать свойства и методы. • В отличие от объектов, массивы имеют свойство length. При присвоении значения к элементу массива, индекс которого больше длины (например, myArray[100] = "hello"), свойство length автоматически увеличивается до новой длины. Аналогично, при уменьшении значения свойства length, любой элемент с индексом за пределами длины массива удаляется.
  • 18. // An array with three elements var myArray = new Array(3); // Add some data myArray[0] = "Hello"; myArray[1] = 42; myArray[2] = new Date(2000, 1, 1); document.write("original length is: " + myArray.length); document.write("<br/>"); // Add some expand properties myArray.expando = "JavaScript!"; myArray["another Expando"] = "Windows"; // This will still display 3, since the two expando properties // don't affect the length. document.write("new length is : " + myArray.length); // Output: // original length is: 3 // new length is : 3
  • 19. 1.6 null Тип данных null имеет только одно значение в JavaScript: значение null. Ключевое слово null невозможно использовать в качестве имени функции или переменной. Переменная, которая содержит null, не содержит допустимых Number, String, Boolean, Array или Object. Можно стереть содержимое переменной (не удаляя переменную), присваивая ей значение null. Обратите внимание, что в JavaScript значение null – не то же самое, что 0 (как в C и C++). Кроме того, оператор typeof в JavaScript определяет значения null как значения типа Object, а не типа null. Такое поведение, которое может запутать разработчиков, используется в целях обратной совместимости.
  • 20. 1.7 undefined Значение undefined возвращается при использовании свойства объекта, которое не существует, или переменной, которая была объявлена, но так и не получила значения. Можно проверить, существует ли переменная, сравнивая ее с undefined, однако можно проверить, является ли ее тип undefined, сравнивая тип переменной со строкой "undefined". В следующем примере показано, как определить, была ли объявлена переменная x:
  • 21. var x; // This method works. if (x == undefined) { document.write("comparing x to undefined <br/>"); } // This method works. if (x == null) { document.write("comparing x to null <br/>"); } // This method doesn't work - you must check for the string "undefined". if (typeof(x) == undefined) { document.write("comparing the type of x to undefined <br/>"); } // This method does work. if (typeof(x) == "undefined") { document.write("comparing the type of x to the string 'undefined'"); } // Output: // comparing x to undefined // comparing x to null // comparing the type of x to the string 'undefined' undefined довольно странный зверек, условно говоря, оно обозначает что "данных нет". Не null, а данных нет. Понимайте как хотите.
  • 22. 1.8 Преобразование типов Преобразование типа можно явным образом сделать через его название: var test = Boolean("something") // true
  • 23. 2. OOP in JavaScript. 2.1 Object Объект в JavaScript – это просто коллекция пар ключ-значение (и немного внутренней магии). Однако, в JavaScript нет концепции класса. К примеру, объект с свойствами {name: Eugene, age: 16} не является экземпляром какого- либо класса или класса Object. И Object, и Eugene являются экземплярами самих себя. Они определяются непосредственно собственным поведением. Тут нет слоя мета-данных (т.е. классов), которые говорили бы этим объектам как нужно себя вести. Сразу возникает вопрос: «WTF?», особенно если вы пришли из мира классических объектно-ориентированных языков (таких как Java или C#). «Но если каждый объект обладает собственным поведением (вместо того чтобы наследовать его от общего класса), то если у меня 100 объектов, то им соответствует 100 разных методов? Разве это не опасно? А как мне узнать, что, например, объект действительно является Array-ем?»
  • 24. Чтобы ответить на все эти вопросы необходимо забыть о классическом ОО- подходе и начать всё с нуля. Оно того стоит. Модель прототипного ОО приносит несколько новых динамичных и экспрессивных путей решения старых проблем. В ней также представлены мощные модели расширения и повторного использования кода (а это и интересует людей, которые говорят об объектно-ориентированном программировании). Однако, эта модель даёт меньше гарантий. Например, нельзя полагаться, что объект x всегда будет иметь один и тот же набор свойств. Объект в JavaScript создаётся с помощью функции Object.create. Эта функция из родителя и опционального набора свойств создаёт новую сущность. Так как объекты — это просто пары уникальных ключей с соответствующими значениями – такие пары называются свойства. К примеру, вы хотите описать несколько аспектов своего старого друга (назовём его Юджин, он же Eugene), таких как возраст, имя и пол. Итак, академический способ:
  • 25. var Eugene = Object.create(null) Классика ООП: var Eugene = new Object() Упрощенная нотация: var Eugene = {}
  • 26. 2.1.1 Свойства объектов Свойства в JavaScript являются динамическими. Это означает, что мы их можем создавать или удалять в любое время. Свойства уникальны в том смысле, что ключ свойства внутри объекта соответствует ровно одному значению. В Javascript есть функция, позволяющая создат свойство объякта, правильно: Object.defineProperty. В качестве аргументов она использует объект, имя свойства для создания и дескриптор, описывающий семантику свойства. Например: Object.defineProperty(Eugene, 'name', { value: 'Eugene' , writable: true , configurable: true , enumerable: true }) Или упрощенно: Eugene.name = 'Eugene' Eugene['name'] = 'Eugene'
  • 27. Для удаления свойства из объекта в JavaSCript предусмотрен оператор delete. К примеру, если вы хотите удалить свойство gender из нашего объекта mikhail: delete Eugene [‘name’] // => true Eugene [‘name’] // => undefined
  • 28. 2.1.2 Геттеры и сеттеры Getter-ы и setter-ы обычно используются в классических объектно-ориентированных языках для обеспечения инкапсуляции. Геттеры и сеттеры в JavaScript позволяет обеспечить proxy для запросов на чтение и запись свойств. Поскольку понятие области видимости в JavaScript нет, то и задач инкапсуляции геттеры/сеттеры не решают. Пример классического определения Геттера/Сеттера: Object.defineProperty(Illya, 'name', { configurable: true, enumerable: true, get: function () { return "My Name is: " + this._name; }, set: function (value) { this._name = value; } });
  • 29. 2.1.3 Методы объекта Описание действий, которые можно делать с объектом делается в JavaScript очень просто. Почему? Да, потому, что в JavaScript нет разницы между манипулированием такими вещами, как Function, Number, Object. Всё делается одинаково. Любой метод является просто свойством текущего объекта типа Function, которое создается динамически и может быть использовано в контексте этого объекта. Пример: var Eugene = { name: "Eugene" }; Eugene.getName = function () { return this.name; }; Eugene.setName = function (value) { this.name = value; };
  • 30. 2.1.4 Что такое this? Магия в действии this – это одна из самых важных переменных в JavaScript, она хранит в себе ссылку на объект, которому принадлежит исполняющаяся функция. Это не обязательно означает, что this всегда равно объекту, в котором функция хранится. Нет, JavaScript не настолько эгоистичен. Функции являются generic-ами. Т.е. в JavaScript переменная this определяет динамическую ссылку, которая разрешается в момент исполнения функции. Процесс динамического разрешения this обеспечивает невероятно мощный механизм для динамизации объектной ориентированности JavaScript и компенсирует отсутствие строгого соответствия заданным структурам (т.е. классам). Это означает, что можно применить функцию к любому объекту, который отвечает требованиям запуска, независимо от того, как устроен объект
  • 31. Существует четыре различных способа разрешения this в функции, зависящие от того, как функция вызывается: • непосредственно, когда функция вызывается сама по себе, без объектного контекста. Например: someFunction1(). В этом слечае this это глобальный контекст (в браузере это объект window) • как метод, например: Eugene.getName(), в таком случае this будет тождественно объекту Eugene. • явно применяется. В JavaScript любая функция может быть вызвана в контексте некоторого объекта используя методы call или apply. Рассмотрим пример:
  • 32. function getObjectQName(parameter1) { var result = "My Name is: " + this.name; if (parameter1 != null) { result += ", and parameter1 is: " + parameter1; } return result; } getObjectQName.call(Eugene, "PAR-1"); // this === Eugene getObjectQName.call(Illya, "PARAMETER-1"); // this === Illya // Bind example Eugene.illyaNameFnc = getObjectQName.bind(Illya); writeLog(Eugene.illyaNameFnc("PAR-1")); // this === Illya
  • 33. • как конструктор. Этот контекст рассмотрим позднее.
  • 34. 2.1.5 Литеральный синтаксис определения объекта Простой способ создать объект заключается в использовании литерального синтаксиса JavaScript. Литеральный объект определяет новый объект, родитель которого Object.prototype. Пример этого синтаксиса приведен ниже: var Eugene = { _name: "Eugene", _age: 18, get name() { return this._name; }, set name(value) { this._name = value; }, getAge: function(){ return this._age; } };
  • 35. 2.1.6 Наследование объектов? • Наследование в JavaScript осуществляется через клонирование поведения объекта и расширение его специализированным поведением. Объект, поведение которого клонируют, называется прототипом. • Прототип – это обычный объект, который делится своим поведением с другими объектами – в этом случае он выступает в качестве родителя. • Концепт клонирования поведения не означает, что вы будете иметь две различные копии одной и той же функции или данных. На самом деле JavaScript реализует наследование через делегирование, т.е. все свойства хранятся в родителе, а доступ к ним расширен через ребёнка. • Как упоминалось ранее, родитель (или [[Prototype]]) объекта определяется вызовом Object.create с первым аргументом, ссылающимся на объект- родитель. Рассмотрим пример:
  • 36. var Person = { _name: "Unknown", _age: 0, get name() { return this._name; }, set name(value) { this._name = value; }, getLocalName: function(){ return "Person: " + this._name; }, getAge: function(){ return this._age; } }; writeLog(Person.name); writeLog(Person.getAge()); var Eugene = Object.create(Person); Eugene.name = "Eugene"; Eugene._age = 18; writeLog(Eugene.name); writeLog(Eugene.getAge()); writeLog(""); writeLog("Dynamically overloading getLocalName() object method"); writeLog(Eugene.getLocalName()); Eugene.getLocalName = function () { return "From Eugene: " + this._name; }; writeLog(Eugene.getLocalName()); delete Eugene.getLocalName; writeLog(Eugene.getLocalName());
  • 37. JavaScript реализует делегирование доступа к свойствам, т.е. свойство ищется через всех родителей объекта. Эта цепь родителей определяется скрытым слотом в каждом объекте, который называется [[Prototype]]. Вы не можете изменить его непосредственно, существует только один способ задать ему значение – при создании нового объекта. Когда свойство запрашивается из объекта, движок сначала пытается получить свойство из целевого объекта. Если свойство не найдено, то рассматривается непосредственный родитель объекта, затем родитель родителя и т.д. Это означает, что мы можем изменить поведение прототипа в середине программы, то автоматически изменится поведение всех объектов, которые были от него унаследованы.
  • 38. 2.2 Class. 2.2.1 Классы Итак, самая большая магия. В JavaScript классы – это функции! WTF? Любая функция, кроме некоторых встроенных, может быть инициализирована как объект. Для этого ее нужно вызвать через директиву new. Итак: RiaShamans.JSExamples.Person = function (name, age, mass) { this.name = name; this.age = age; this.mass = mass; }; var Eugene = new ("Eugene", 18, 65);
  • 39. Во время работы функции, вызванной директивой new, новосоздаваемый объект доступен как this, так что можно проставить любые свойства. Класс объекта определяется функцией, которая его создала. Для проверки принадлежности классу есть оператор instanceof: var Eugene = new RiaShamans.JSExamples.Person("Eugene", 18, 65); writeLog(Eugene instanceof RiaShamans.JSExamples.Person);
  • 40. 2.2.2 Пространства имен и пакеты Поскольку классы и объекты реализуются в виде переменных (переменных- функций и переменных-объектов), то пространства имен могут быть реализованы в виде полей-переменных Объектов. Например: if (typeof(RiaShamans) == "undefined") RiaShamans = {}; if (typeof(RiaShamans.JSExamples) == "undefined") RiaShamans.JSExamples = {}; Таким образом создан пакет RiaShamans.JSExamples, который может использоваться для определения классов или объектов. Например:
  • 41. if (typeof(RiaShamans) == "undefined") RiaShamans = {}; if (typeof(RiaShamans.JSExamples) == "undefined") RiaShamans.JSExamples = {}; /** * Class defines Person Entity * * @class {RiaShamans.JSExamples.Person} * @param name * @param age * @param mass * @returns {RiaShamans.JSExamples.Person} */ RiaShamans.JSExamples.Person = function (name, age, mass) { };
  • 42. 2.2.3 Классы и прототипы. Наследование В javascript базовое наследование основано не на классах. То есть, нет такого, что классы наследуют друг от друга, а объект класса-потомка получает общие свойства. Вместо этого объекты наследуют от объектов без всяких классов. Наследование на классах можно построить(эмулировать), опираясь на базовое наследование javascript. Реализуется наследование через неявную(внутреннюю) ссылку одного объекта на другой, который называется его прототипом и в спецификации обозначается [[prototype]]. Это свойство обычно скрыто от программиста. Также существует свойство с похожим названием prototype (без квадратных скобок) – оно вспомогательное и указывает, откуда брать прототип при создании объекта. Когда вы ставите функции Person свойство Person.prototype = XXX – вы этим декларируете: "все новые объекты класса Person будут иметь прототип XXX". Рассмотрим пример:
  • 43. if (typeof(RiaShamans) == "undefined") RiaShamans = {}; if (typeof(RiaShamans.JSExamples) == "undefined") RiaShamans.JSExamples = {}; /** * Class defines Person Entity * * @class {RiaShamans.JSExamples.Person} * @param name * @param age * @param mass * @returns {RiaShamans.JSExamples.Person} */ RiaShamans.JSExamples.Person = function (name, age, mass) { this.initPerson(name, age, mass); }; RiaShamans.JSExamples.Person.prototype.constructor = RiaShamans.JSExamples.Person; /** * Initialize person Data * * @param name * @param age * @param mass */ RiaShamans.JSExamples.Person.prototype.initPerson = function(name, age, mass){ this.name = name; this.age = age; this.mass = mass; };
  • 44. /** * Returns Person name * * @returns {String} */ RiaShamans.JSExamples.Person.prototype.getName = function(){ return this.name; }; /** * Returns person Age * * @returns Number */ RiaShamans.JSExamples.Person.prototype.getAge = function(){ return this.age; }; /** * Class defines gendered Person Entity * * @class {RiaShamans.JSExamples.GenderPerson} * @augments {RiaShamans.JSExamples.Person} * @lends {RiaShamans.JSExamples.Person.prototype} */ RiaShamans.JSExamples.GenderPerson = function (name, age, mass) { // Inherit parent constructor RiaShamans.JSExamples.GenderPerson.superclass.constructor.call(this, name, age, mass); // this is equivalent of RiaShamans.JSExamples.Person.call(this, name, age, mass); this.gender = "UNKNOWN"; };
  • 45. // Implement Inheritance var GenderPersonPrototype = function(){}; GenderPersonPrototype.prototype = RiaShamans.JSExamples.Person.prototype; // Create prototype without parameters. We can't Instantiate Parent without proper data in some cases. RiaShamans.JSExamples.GenderPerson.prototype = new GenderPersonPrototype(); // Add all parent prototype data to Child class RiaShamans.JSExamples.GenderPerson.prototype.constructor = RiaShamans.JSExamples.GenderPerson; // Set constructor RiaShamans.JSExamples.GenderPerson.superclass = RiaShamans.JSExamples.Person.prototype; // Set superclass for Child /** * Returns Gender * * @returns {String} */ RiaShamans.JSExamples.GenderPerson.prototype.getGender = function(){ return this.gender; }; /** * Set Gender for a Person * * @param value */ RiaShamans.JSExamples.GenderPerson.prototype.setGender = function(value){ this.gender = value; };
  • 46. 2.2.4 Статические методы Поскольку классы в JavaScript (они же функции), это в свою очередь объекты, то для них можно определять поля в виде функций. Такая функция будет доступна без инициализации объекта класса и в контексте самого класса, являясь аналогом статического метода в классическом ООП. Рассмотрим пример:
  • 47. /** * Factory class. Example of static methods * * @class {RiaShamans.JSExamples.PersonFactory} * @lends {RiaShamans.JSExamples.PersonFactory.prototype} */ RiaShamans.JSExamples.PersonFactory = function(){ }; /** * Factory method. creates person and returns its instance * * @returns {RiaShamans.JSExamples.Person} */ RiaShamans.JSExamples.PersonFactory.createPerson = function(name, age, mass){ var result = new RiaShamans.JSExamples.Person(name, age, mass); return result; };