<b> // но также с текстовыми диапазонами и с диапазонами дат Date,</b>
<b> includes: function(x) { return this.from <= x && x <= this.to; },</b>
<b> // Вызывает f для каждого целого числа в диапазоне.</b>
<b> // Этот метод может работать только с числовыми диапазонами,</b>
<b> foreach: function(f) {</b>
<b> for(var х = Math.ceil(this.from); x <= this.to; x++) f(x);</b>
<b> }</b>
<b> // Возвращает строковое представление диапазона</b>
<b> toString: function() { return "(" + this.from + "..." + this.to + ")" }</b>
<b>}</b>
<b>// Ниже приводится пример использования объекта range.</b>
<b>var r = range(1,3); </b><div class="fb2-code"><code><b>// Создать новый объект range </b></code></div>
<b>r.includes(2); </b><div class="fb2-code"><code><b>// =&gt; true: число 2 входит в диапазон </b></code></div>
<b>r.foreach(console.log);</b><div class="fb2-code"><code><b>// Выведет 1 2 3 </b></code></div>
<b>console.log(r); </b>
<b>// Выведет (1...3)</b>
В примере 9.1 есть несколько интересных моментов, которые следует отметить особо. Здесь определяется фабричная функция
<b>range(),</b>
которая используется для создания новых объектов
<b>range</b>
. Обратите внимание, что для хранения объекта-прототипа, определяющего класс, используется свойство
<b>range.methods</b>
функции
<b>range().</b>
В таком способе хранения объекта-прототипа нет ничего необычного. Во-вторых, отметьте, что функция
<b>range()</b>
определяет свойства
<b>from</b>
и
<b>to</b>
для каждого объекта
<b>range</b>
. Эти не общие, не унаследованные свойства определяют уникальную информацию для каждого отдельного объекта range. Наконец, обратите внимание, что все общие, унаследованные методы, определяемые свойством
<b>range.methods</b>
, используют свойства
<b>from</b>
и
<b>to</b>
и ссылаются на них с помощью ключевого слова
<b>this</b>
, указывающего на объект, относительно которого вызываются эти методы. Такой способ использования this является фундаментальной характеристикой методов любого класса.
9.2. Классы и конструкторы
В примере 9.1 демонстрируется один из способов определения класса в языке JavaScript. Однако это не самый типичный способ, потому что он не связан с определением конструктора. Конструктор - это функция, предназначенная для инициализации вновь созданных объектов. Как описывалось в разделе 8.2.3, конструкторы вызываются с помощью ключевого слова
<b>new</b>
. Применение ключевого слова
<b>new</b>
при вызове конструктора автоматически создает новый объект, поэтому конструктору остается только инициализировать свойства этого нового объекта. Важной особенностью вызова конструктора является использование свойства
<b>prototype</b>
конструктора в качестве прототипа нового объекта. Это означает, что все объекты, созданные с помощью одного конструктора, наследуют один и тот же объект-прототип и, соответственно, являются членами одного и того же класса. В примере 9.2 демонстрируется, как можно было бы реализовать класс
<b>range</b>
, представленный в примере 9.1, не с помощью фабричной функции, а с помощью функции конструктора:
Пример 9.2. Реализация класса Range с помощью конструктора
<b>// range2.js: Еще один класс, представляющий диапазон значений.</b>
<b>// Это функция-конструктор, которая инициализирует новые объекты Range.</b>
<b>// Обратите внимание, что она не создает и не возвращает объект.</b>
<b>// Она лишь инициализирует его. </b>
<b>function Range(from, to) {</b>
<b> // Сохранить начальное и конечное значения в новом объекте range.</b>
<b> // Это не унаследованные свойства, и они являются уникальными для данного объекта, </b>
<b> this.from = from; </b>
<b> this.to = to;</b>
<b>}</b>
<b>// Все объекты Range наследуют свойства этого объекта.</b>
<b>// Обратите внимание, что свойство обязательно должно иметь имя "prototype".</b>
<b>Range.prototype = {</b>
<b> // Возвращает true, если х - объект класса range, в противном случае возвращает false </b>
<b> // Этот метод может работать не только с числовыми диапазонами, но также </b>
<b> // с текстовыми диапазонами и с диапазонами дат Date, </b>
<b> includes: function(x) { return this.from <= x && x <= this.to; },</b>
<b> // Вызывает f для каждого целого числа в диапазоне.</b>
<b> // Этот метод может работать только с числовыми диапазонами, </b>
<b> foreach: function(f) {</b>
<b> for(var х = Math.ceil(this.from); x <= this.to; x++) f(x);</b>
<b> },</b>