Чтение онлайн

на главную - закладки

Жанры

JavaScript. Подробное руководство, 6-е издание
Шрифт:

// Возвращает строковое представление диапазона

toString: function { return "(" + this, from + "..." + this, to + ")"; }

};

// Ниже приводится пример использования объекта range.

var r = new Range(1.3); // Создать новый объект range

r.includes(2); // => true: число 2 входит в диапазон

r.foreach(console.log); // Выведет 1 2 3

console.log(r); //
Выведет (1...3)

Имеет смысл детально сравнить примеры 9.1 и 9.2 и отметить различия между этими двумя способами определения классов. Во-первых, обратите внимание, что при преобразовании в конструктор фабричная функция

range
была переименована в
Range.
Это обычное соглашение по оформлению: функции-конструкторы в некотором смысле определяют классы, а имена классов начинаются с заглавных символов. Имена обычных функций и методов начинаются со строчных символов.

Далее отметьте, что конструктор

Range
вызывается (в конце примера) с ключевым словом
new
, тогда как фабричная функция
range
вызывается без него. В примере 9.1 для создания нового объекта использовался вызов обычной функции (раздел 8.2.1), а в примере 9.2 - вызов конструктора (раздел 8.2.3). Поскольку конструктор
Range
вызывается с ключевым словом
new
, отпадает необходимость вызывать функцию
inherit
или предпринимать какие-либо другие действия по созданию нового объекта. Новый объект создается автоматически перед вызовом конструктора и доступен в конструкторе как значение
this
. Конструктору
Range
остается лишь инициализировать его. Конструкторы даже не должны возвращать вновь созданный объект. Выражение вызова конструктора автоматически создает новый объект, вызывает конструктор как метод этого объекта и возвращает объект. Тот факт, что вызов конструктора настолько отличается от вызова обычной функции, является еще одной причиной, почему конструкторам принято давать имена, начинающиеся с заглавного символа. Конструкторы предназначены для вызова в виде конструкторов, с ключевым словом
new
, и обычно при вызове в виде обычных функций они не способны корректно выполнять свою работу. Соглашение по именованию конструкторов, обеспечивающее визуальное отличие имен конструкторов от имен обычных функций, помогает программистам не забывать использовать ключевое слово
new
.

Еще одно важное отличие между примерами 9.1 и 9.2 заключается в способе именования объекта-прототипа. В первом примере прототипом было свойство

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

Наконец, обратите также внимание на одинаковые фрагменты примеров 9.1 и 9.2: в обоих классах методы объекта range определяются и вызываются одинаковым способом.

9.2.1. Конструкторы и идентификация класса

Как видите, объект-прототип играет чрезвычайно важную роль в идентификации класса: два объекта являются экземплярами одного класса, только если они наследуют один и тот же объект-прототип. Функция-конструктор, инициализирующая свойства нового объекта, не является определяющей: два конструктора могут иметь свойства

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

Хотя конструкторы не играют такую же важную роль в идентификации класса, как прототипы, тем не менее конструкторы выступают в качестве фасада класса. Например, имя конструктора обычно используется в качестве имени класса. Так, принято говорить, что конструктор

Range
создает объекты класса
Range
. Однако более важным применением конструкторов является их использование в операторе
instanceof
при проверке принадлежности объекта классу. Если имеется объект r, и необходимо проверить, является ли он объектом класса
Range
, такую проверку можно выполнить так:

r instanceof Range // вернет true, если r наследует Range.prototype

В действительности оператор

instanceof
не проверяет, был ли объект r инициализирован конструктором
Range
. Он проверяет, наследует ли этот объект свойство
Range.prototype
. Как бы то ни было, синтаксис оператора
instanceof
закрепляет использование конструкторов в качестве идентификаторов классов. Мы еще встретимся с оператором
instanceof
далее в этой главе.

9.2.2. Свойство constructor

В примере 9.2 свойству

Range.prototype
присваивался новый объект, содержащий методы класса. Хотя было удобно определить методы как свойства единственного объекта-литерала, но при этом совершенно не было необходимости создавать новый объект. Роль конструктора в языке JavaScript может играть любая функция, поскольку выражению вызова конструктора необходимо лишь свойство
рrototype
. Следовательно, любая функция (кроме функций, возвращаемых методом
Function.bind
в ECMAScript 5) автоматически получает свойство
prototype
. Значением этого свойства является объект, который имеет единственное неперечислимое свойство
constructor
. Значением свойства
constructor
является объект функции:

var F = function {};
// Это объект функции.

var р = F.prototype;
// Это объект-прототип, связанный с ней.

var c = p.constructor;
// Это функция, связанная с прототипом.

c === F
// => true: F.prototype.constructor === F для всех функций

Наличие предопределенного объекта-прототипа со свойством

constructor
означает, что объекты обычно наследуют свойство
constructor
, которое ссылается на их конструкторы. Поскольку конструкторы играют роль идентификаторов классов, свойство
constructor
определяет класс объекта:

var о = new F; // Создать объект класса F

о.constructor === F // => true: свойство constructor определяет класс

Поделиться:
Популярные книги

Солнечный корт

Сакавич Нора
4. Все ради игры
Фантастика:
зарубежная фантастика
5.00
рейтинг книги
Солнечный корт

О, мой бомж

Джема
1. Несвятая троица
Любовные романы:
современные любовные романы
5.00
рейтинг книги
О, мой бомж

Возвышение Меркурия. Книга 2

Кронос Александр
2. Меркурий
Фантастика:
фэнтези
5.00
рейтинг книги
Возвышение Меркурия. Книга 2

Вы не прошли собеседование

Олешкевич Надежда
1. Укротить миллионера
Любовные романы:
короткие любовные романы
5.00
рейтинг книги
Вы не прошли собеседование

Метаморфозы Катрин

Ром Полина
Фантастика:
фэнтези
8.26
рейтинг книги
Метаморфозы Катрин

Эволюция мага

Лисина Александра
2. Гибрид
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Эволюция мага

Попаданка для Дракона, или Жена любой ценой

Герр Ольга
Любовные романы:
любовно-фантастические романы
7.17
рейтинг книги
Попаданка для Дракона, или Жена любой ценой

Истинная поневоле, или Сирота в Академии Драконов

Найт Алекс
3. Академия Драконов, или Девушки с секретом
Любовные романы:
любовно-фантастические романы
6.37
рейтинг книги
Истинная поневоле, или Сирота в Академии Драконов

Сумеречный Стрелок 5

Карелин Сергей Витальевич
5. Сумеречный стрелок
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сумеречный Стрелок 5

Кодекс Охотника. Книга XXI

Винокуров Юрий
21. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XXI

Возвышение Меркурия. Книга 17

Кронос Александр
17. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 17

Переиграть войну! Пенталогия

Рыбаков Артем Олегович
Переиграть войну!
Фантастика:
героическая фантастика
альтернативная история
8.25
рейтинг книги
Переиграть войну! Пенталогия

Волков. Гимназия №6

Пылаев Валерий
1. Волков
Фантастика:
попаданцы
альтернативная история
аниме
7.00
рейтинг книги
Волков. Гимназия №6

Картофельное счастье попаданки

Иконникова Ольга
Фантастика:
фэнтези
5.00
рейтинг книги
Картофельное счастье попаданки