<b> return this;</b>
<b> },</b>
<b> difference: function(that) {</b>
<b> var self = this;</b>
<b> that.foreach(function(v) { self.remove(v); });</b>
<b> return this;</b>
<b> }</b>
<b> });</b>
<b>/*</b>
<b> * ArraySet - конкретный подкласс класса AbstractWritableSet.</b>
<b> * Представляет множество элементов как массив значений и реализует линейный</b>
<b> * поиск в массиве в своем методе contains(). Поскольку алгоритм метода containsO</b>
<b> * имеет сложность 0(п) вместо 0(1), данный класс следует использовать только</b>
<b> * для создания относительно небольших множеств.</b>
<b> * Обратите внимание, что эта реализация опирается на методы класса Array</b>
<b> * indexOfO и forEach(), которые определяются стандартом ES5.</b>
<b>*/</b>
<b>var ArraySet = AbstractWritableSet.extend(</b>
<b> function ArraySet() {</b>
<b> this.values = [];</b>
<b> this.add.apply(this, arguments);</b>
<b> },</b>
<b> {</b>
<b> contains: function(v) {</b>
<b> return this.values.indexOf(v) != -1;</b>
<b> },</b>
<b> size: function() {</b>
<b> return this.values.length;</b>
<b> },</b>
<b> foreach: function(f.c) {</b>
<b> this.values.forEach(f, c);</b>
<b> },</b>
<b> add: function() {</b>
<b> for(var і = 0; і < arguments.length; i++) {</b>
<b> var arg = arguments[i];</b>
<b> if (Ithis.contains(arg)) this.values.push(arg);</b>
<b> }</b>
<b> return this;</b>
<b> },</b>
<b> remove: function() {</b>
<b> for(var і = 0; і < arguments.length; i++) {</b>
<b> var p = this.values.indexOf(arguments[i]);</b>
<b> if (p == -1) continue;</b>
<b> this.values.splice(p, 1);</b>
<b> )</b>
<b> return this;</b>
<b> }</b>
<b>}</b>
<b>);</b>
9.8. Классы в ECMAScript 5
Стандарт ECMAScript 5 добавляет методы, позволяющие определять атрибуты свойств (методы чтения и записи, а также признаки доступности для перечисления, записи и настройки) и ограничивать возможность расширения объектов. Эти методы были описаны в разделах 6.6, 6.7 и 6.8.3 и могут пригодиться при определении классов. В следующих подразделах демонстрируется, как использовать новые возможности ECMAScript 5 для повышения надежности своих классов.
9.8.1. Определение неперечислимых свойств
Класс
<b>Set</b>
, представленный в примере 9.6, вынужден использовать уловку, чтобы обеспечить возможность сохранения объектов: он добавляет свойство «object id» ко всем объектам, добавляемым в множество. Если позднее в каком-то другом месте программы будет выполнен обход свойств этого объекта с помощью цикла
<b>for/in</b>
, это свойство будет обнаружено. Стандарт ECMAScript 5 позволяет исключить такую возможность, сделав свойство неперечислимым. В примере 9.17 демонстрируется, как это сделать с помощью
<b>Object.defineProperty(),</b>
а также показывает, как определить метод чтения и как проверить возможность расширения объекта.
Пример 9.17. Определение неперечислимых свойств
<b>// Обертывание программного код функцией позволяет определять переменные </b>
<b>// в области видимости функции </b>
<b>(function() {</b>
<b> // Определить свойство objectId как неперечислимое и наследуемое </b>
<b> // всеми объектами. При попытке получить значение этого свойства </b>
<b> // вызывается метод чтения. Свойство не имеет метода записи, поэтому </b>
<b> // оно доступно только для чтения. Свойство определяется как ненастраиваемое,</b>
<b> // поэтому его нельзя удалить.</b>
<b> Object.defineProperty(Object.prototype, "objectld", {</b>
<b> get: idGetter, // Метод чтения значения</b>
<b> enumerable: false, // Неперечислимое</b>
<b> configurable: false // He может быть удалено</b>
<b> });</b>
<b> // Функция чтения, которая вызывается при попытке получить значение</b>
<b> // свойства objectld</b>