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

<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; і &lt; 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; і &lt; 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, &quot;objectld&quot;, {</b>

<b>    get: idGetter, // Метод чтения значения</b>

<b>    enumerable: false, // Неперечислимое</b>

<b>    configurable: false // He может быть удалено</b>

<b>  });</b>

<b>  // Функция чтения, которая вызывается при попытке получить значение</b>

<b>  // свойства objectld</b>