В этой лекции мы рассмотрим различные способы создания свойств и методов у объекта и то, какие плюсы это может вам дать. Итак, воспользуемся уже знакомым нам методом Object.keys для нашего объекта tweet с методом toString. Как мы видим, мы получаем в результате вызова массив, который состоит из одного элемента, строчки toString с именем метода, который у нас объявлен явно. Возьмем пустой объект, у которого нет ни свойств, ни методов, и так же вызовем его Object.keys. Получим пустой массив, что, в общем-то, логично: ни свойств, ни методов у объекта не объявлено. Теперь проверим существование функции toString у объекта с твитом и мы увидим, что такая функция существует. И проверим ее существование у пустого объекта и мы увидим, что она тоже есть. Как так получается, что у обоих объектов функция есть, и она вызываема, но при этом у первого она задекларирована явно, а у второго мы ее не видим, и Object.keys обозначает пустоту. Дело в том, что есть различные способы декларации функций и методов у объектов, и явная декларация при создании литерального объекта — это только один из способов. Рассмотрим другой. Создадим пустой на этот раз объект твита и воспользуемся специальным методом defineProperty. Этот метод принимает на вход объект, для которого мы хотим задекларировать новое свойство или метод, имя этого свойства, которое будет создано, а также так называемый объект конфигурирования, который описывает параметры свойства, которое мы хотим создать, или параметры метода, который мы хотим создать, если это метод. Одно из полей этого объекта — это поле value, которое может быть примитивом, а может быть функцией. Если это функция, то это будет метод объекта, а если это будет примитив, то это будет просто свойство, к которому можно будет обратиться. Также у него есть ряд других свойств, которые вы можете сконфигурировать. О них мы поговорим немного попозже. Также существует метод define.Properties, который позволяет сразу же задекларировать несколько свойств у объекта О нем вы можете почитать подробнее, перейдя по ссылке, прикрепленной к видео. Итак, у объекта конфигурирования есть несколько полей: writable, enumerable и configurable. По умолчанию значения у них всегда false, и их можно явно не прописывать, если вы хотите выставить именно это значение для них. Что же каждый из них делает? Начнем с writable. Создадим пустой твит, задекларируем у него свойство text с текстом нашего твита и скажем, что оно wirtable со значением false, то есть нередактируемое. Воспользуемся специальным методом getOwnPropertyDescriptor, который возвращает вам данные об объекте конфигурирования для объекта и любого свойства этого объекта. В данном случае мы видим, что мы создали свойство, которое имеет текстовое значение в виде примитива, в виде строки, и поля wirable, configurable и enumerable представлены false. Как я уже говорил, false — это значение по умолчанию, поэтому то, что мы не указали ни configurable, ни enumerable для объекта конфигурирования неважно. Итак, мы можем обратиться к этому свойству, таким образом мы получим текст нашего твита. Теперь попытаемся изменить значение этого свойства, приравняв ему новое значение. Операция пройдет, но при этом ничего не произойдет. Значение свойства не изменится, и оно останется предыдущим. Enumerable. Это свойство отвечает за то, является ли свойство или метод перечислимым или неперечислимым. Итак, пустой объект твита. На этот раз мы создаем то же самое поле, но говорим ему enumerable false. Проверяем, что объект конфигурирования именно тот, которого мы ожидали, с помощью getOwnPropertyDescriptor, И теперь воспользуемся методом Object.keys для данного твита. И мы видим, что мы получаем пустой массив. Свойство есть, оно работает, оно доступно, но мы не видим его в списке свойств, оно как бы скрыто от нас. Configurable. Это свойство отвечает за редактирование нашего метода или редактирование нашего свойства и за его удаление. Пустой твит, декларируем новое свойство text с configurable false, проверяем, что свойство создано и создано корректно, обращаемся к нему, получаем текст нашего твита. А теперь пытаемся удалить его с помощью оператора delete. Как мы видим, оператор вернул нам false, удаление не произошло. Снова обращаемся к свойству — и да, свойство есть, и оно никуда не делось. Теперь это свойство нередактируемое, мы не можем переопределить его с помощью defineProperty, и мы не можем удалить его с помощью оператора delete.