<b> var names; // Массив имен свойств</b>
<b> if (arguments.length == 0) // Все собственные свойства объекта this</b>
<b> names = Object.getOwnPropertyNames(this);</b>
<b> else if (arguments.length == 1 && Array.isArray(arguments[0]))</b>
<b> names = arguments[0]; // Или массив указанных свойств </b>
<b> else // Или имена в списке аргументов</b>
<b> names = Array.prototype.splice.call(arguments, 0);</b>
<b> // Вернуть новый объект Properties, представляющий указанные свойства return</b>
<b> new Properties(this, names);</b>
<b> }</b>
<b> // Делает эту функцию новым, неперечислимым свойством Object.prototype.</b>
<b> // Это единственное значение, экспортируемое из частной области видимости функции.</b>
<b> Object.defineProperty(Object.prototype, "properties", {</b>
<b> value: properties,</b>
<b> enumerable: false,</b>
<b> writable: true,</b>
<b> configurable: true</b>
<b> });</b>
<b> // Следующая функция-конструктор вызывается функцией properties().</b>
<b> // Класс Properties представляет множество свойств объекта,</b>
<b> function Properties(), names) {</b>
<b> this.о = о; // Объект, которому принадлежат свойства</b>
<b> this.names = names; // Имена свойств</b>
<b> }</b>
<b> // Делает неперечислимыми свойства, представленные объектом this</b>
<b> Properties.prototype.hide = function() {</b>
<b> var о = this.o, </b>
<b>hidden = { enumerable: false };</b>
<b> this.names.forEach(function(n) {</b>
<b> if (o.hasOwnProperty(n))</b>
<b> Object.defineProperty(o, n, hidden);</b>
<b> });</b>
<b> return this;</b>
<b> };</b>
<b> // Делает свойства ненастраиваемыми и доступными только для чтения</b>
<b> Properties.prototype.freeze = function() {</b>
<b> var о = this.o, frozen = { writable: false, configurable: false };</b>
<b> this.names.forEach(function(n) {</b>
<b> if (o.hasOwnProperty(n))</b>
<b> Object.defineProperty(o, n, frozen);</b>
<b> }):</b>
<b> return this;</b>
<b> };</b>
<b> // Возвращает объект, отображающий имена свойств в дескрипторы.</b>
<b> // Может использоваться для реализации копирования свойств вместе с их атрибутами:</b>
<b> // Object.defineProperties(dest, src.properties().descriptors());</b>
<b> Properties.prototype.descriptors = function() {</b>
<b> var о = this.o, desc = {};</b>
<b> this.names.forEach(function(n) {</b>
<b> if (lo.hasOwnProperty(n)) return;</b>
<b> desc[n] = Object.getOwnPropertyDescriptor(o, n);</b>
<b> });</b>
<b> return desc;</b>
<b> };</b>
<b> // Возвращает отформатированный список свойств, в котором перечислены имена,</b>
<b> // значения и атрибуты свойств. Термин "permanent" используется для обозначения</b>
<b> // ненастраиваемых свойств, "readonly" - для обозначения свойств, не доступных</b>
<b> // для записи, и "hidden" - для обозначения неперечислимых свойств.</b>
<b> // Обычные перечислимые, доступные для записи и настраиваемые свойства</b>
<b> // указываются в списке без атрибутов.</b>
<b> Properties.prototype.toString = function() {</b>
<b> var о = this.o; // Используется во вложенных функциях ниже</b>
<b> var lines = this.names.map(nameToString);</b>
<b> return "{\n " + lines.join(",\n ") + "\n}";</b>
<b> function nameToString(n) {</b>
<b> var s = desc = Object.getOwnPropertyDescriptor(o, n);</b>
<b> if (!desc) return "nonexistent " + n + ": undefined";</b>
<b> if (!desc.configurable) s += "permanent ";</b>
<b> if ((desc.get && Idesc.set) || !desc.writable) s += "readonly ";</b>