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

<b>* конструктора. Обратите внимание, что в методах класса вообще не используется</b>

<b>* ключевое слово this: они выполняют операции только со своими аргументами.</b>

<b>*/</b>

<b>// Ниже определяется несколько полей класса, хранящих предопределенные</b>

<b>// комплексные числа. Их имена состоят исключительно из заглавных символов,</b>

<b>// чтобы показать, что они являются константами.</b>

<b>// (В ECMAScript 5 эти свойства можно было бы сделать доступными только для чтения)</b>

<b>Complex.ZERO = new Complex(0,0);</b>

<b>Complex.ONE = new Complex(1,0);</b>

<b>Complex.I = new Complex(0,1);</b>

<b>// Следующий метод анализирует строку в формате, возвращаемом методом</b>

<b>// экземпляра toString, и возвращает объект Complex или возбуждает исключение ТуреЕггог.</b>

<b>Complex.parse = function(s) {</b>

<b>  try { // Предполагается, что анализ пройдет успешно</b>

<b>    var m = Complex._format.exec(s); // Регулярное выражение </b>

<b>    return new Complex(parseFloat(m[1]), parseFloat(m[2]));</b>

<b>  } catch (x) { // Возбудить исключение в случае неудачи</b>

<b>    throw new TypeError(&quot;Строка + s + &quot;' не может быть преобразована” +</b>

<b>                         в комплексное число.&quot;);</b>

<b>  }</b>

<b>};</b>

<b>// &quot;Частное&quot; поле класса, используемое методом Complex.parse().</b>

<b>// Символ подчеркивания в его имени указывает, что оно предназначено</b>

<b>// для внутреннего использования и не является частью общедоступного API класса.</b>

<b>Complex._format = /^\{([^,]+),([^}]+)\}$/;</b>

Определение класса Complex, представленное в примере 9.3, позволяет использовать конструктор, поля экземпляра, методы экземпляров, поля класса и методы класса, как показано ниже:

<b>var с = new Complex(2,3);     // Создать новый объект с помощью конструктора</b>

<b>var d = new Complex(c.i.c.r); // Использовать свойства экземпляра с </b>

<b>c.add(d).toString();          // =&gt; &quot;{5.5}&quot;: использовать методы экземпляров</b>

<b>// Более сложное выражение, в котором используются метод и поле класса </b>

<b>Complex.parse(c.toStringO).   // Преобразовать с в строку и обратно, </b>

<b>add(c.neg()).                 // сложить с числом с противоположным знаком,</b>

<b>equals(Complex.ZERO)          // и результат всегда будет равен нулю</b>

Несмотря на то что язык JavaScript позволяет имитировать члены классов в стиле языка Java, тем не менее в Java существует множество особенностей, которые не поддерживаются классами в языке JavaScript. Во-первых, в методах экземпляров классов в языке Java допускается использовать поля экземпляра, как если бы они были локальными переменными, - в Java нет необходимости предварять их ссылкой

<b>this</b>
. В языке JavaScript такая возможность не поддерживается, но похожего эффекта можно добиться с помощью инструкции with (хотя это и не рекомендуется):

<b>Complex.prototype.toString = function() { </b>

<b>  with(this) {</b>

<b>    return + r + &quot; + і +</b>

<b>  }</b>

<b>}; </b>

В языке Java поддерживается возможность объявлять поля со спецификатором

<b>final</b>
, чтобы показать, что они являются константами, и объявлять поля и методы со спецификатором
<b>private</b>
, чтобы показать, что они являются частными для реализации класса и недоступны пользователям класса. В языке JavaScript эти ключевые слова отсутствуют, поэтому, чтобы обозначить частные свойства (имена которых начинаются с символа подчеркивания) и свойства, доступные только для чтения (имена которых содержат только заглавные символы), в примере 9.3 используются соглашения по именованию. Мы еще вернемся к этим двум темами ниже в этой главе: частные свойства можно имитировать с помощью локальных переменных в замыканиях (раздел 9.6.6), а возможность определения свойств-констант поддерживается стандартом ECMAScript 5 (раздел 9.8.2).

9.4. Наращивание возможностей классов

Механизм наследования на основе прототипов, используемый в языке JavaScript, имеет динамическую природу: объекты наследуют все свойства своих прототипов, даже если они были добавлены в прототипы уже после создания объектов. Это означает, что в JavaScript имеется возможность наращивать возможности классов простым добавлением новых методов в объекты-прототипы. Ниже приводится фрагмент, который добавляет метод вычисления сопряженного комплексного числа в класс

<b>Complex</b>
из примера 9.3:

<b>// Возвращает комплексное число, которое является сопряженным </b>

<b>// по отношению к текущему.</b>

<b>Complex.prototype.conj = function() { return new Complex(this.r, -this.i); };</b>

Объект-прототип встроенных классов JavaScript также «открыт» для подобного наращивания, а это означает, что есть возможность добавлять новые методы к числам, строкам, массивам, функциям и т. д. Данная возможность уже использовалась в примере 8.5. Там мы добавляли метод

<b>bind()</b>
к классу функций в реализации ECMAScript 3, где он отсутствует:

<b>if (!Function.prototype.bind) {</b>