Я посмотрел вокруг, как использовать Object.defineProperty
метод, но не смог найти ничего приличного.
Кто-то дал мне этот фрагмент кода :
Object.defineProperty(player, "health", {
get: function () {
return 10 + ( player.level * 15 );
}
})
Но я этого не понимаю. Главным образом, get
это то, что я не могу получить (каламбур). Как это работает?
javascript
object
defineproperty
Математический чиллер
источник
источник
Ответы:
Поскольку вы задали похожий вопрос , давайте рассмотрим его шаг за шагом. Это немного дольше, но это может сэкономить вам гораздо больше времени, чем я потратил на написание этого:
Свойство - это функция ООП, предназначенная для чистого разделения клиентского кода. Например, в каком-то интернет-магазине у вас могут быть такие объекты:
Затем в своем клиентском коде (интернет-магазине) вы можете добавить скидки на свои товары:
Позже владелец интернет-магазина может понять, что скидка не может превышать 80%. Теперь вам нужно найти КАЖДЫЙ случай изменения скидки в коде клиента и добавить строку
Затем владелец интернет-магазина может изменить свою стратегию, например, «если клиент является реселлером, максимальная скидка может составлять 90%» . И вам нужно снова вносить изменения в нескольких местах, а также помнить об изменении этих строк при каждом изменении стратегии. Это плохой дизайн. Вот почему инкапсуляция является основным принципом ООП. Если конструктор был такой:
Затем вы можете просто изменить методы
getDiscount
( accessor ) иsetDiscount
( mutator ). Проблема в том, что большинство участников ведут себя как общие переменные, просто скидка здесь требует особого внимания. Но хороший дизайн требует инкапсуляции каждого элемента данных, чтобы сохранить код расширяемым. Так что вам нужно добавить много кода, который ничего не делает. Это тоже плохой дизайн, шаблонный антипаттерн . Иногда вы не можете просто рефакторизовать поля для методов позже (код eshop может стать большим или какой-то сторонний код может зависеть от старой версии), поэтому шаблон здесь меньше зла. Но все же это зло. Вот почему свойства были введены во многих языках. Вы можете сохранить оригинальный код, просто превратив член скидки в собственность сget
иset
блоки:Обратите внимание на последнюю, но одну строку: ответственность за правильное значение скидки была перенесена из кода клиента (определение интернет-магазина) в определение продукта. Продукт отвечает за поддержание согласованности своих данных. Хороший дизайн (грубо говоря), если код работает так же, как наши мысли.
Так много о свойствах. Но javascript отличается от чисто объектно-ориентированных языков, таких как C #, и по-разному кодирует функции:
В C # преобразование полей в свойства является серьезным изменением , поэтому открытые поля должны быть закодированы как автоматически реализуемые свойства, если ваш код может использоваться в отдельно скомпилированном клиенте.
В Javascript стандартные свойства (элемент данных с геттером и сеттером, описанным выше) определяются дескриптором доступа (по ссылке, которая у вас есть в вашем вопросе). Исключительно, вы можете использовать дескриптор данных (так что вы не можете использовать т.е. значение и установить одно и то же свойство):
Оба дескриптора могут иметь следующие члены:
for(var i in theObject)
; если false, он не будет повторяться, но все еще доступен как общедоступный* если не в строгом режиме - в этом случае JS останавливает выполнение с помощью TypeError, если только он не перехвачен в блоке try-catch
Чтобы прочитать эти настройки, используйте
Object.getOwnPropertyDescriptor()
.Учитесь на примере:
Если вы не хотите разрешать клиенту кодировать такие читы, вы можете ограничить объект тремя уровнями ограничения:
Object.isExtensible(<yourObject>)
чтобы проверить, был ли метод использован на объекте. Профилактика мелкая (читайте ниже).configurable: false
все свойства). ИспользуйтеObject.isSealed(<yourObject>)
для обнаружения этой функции на объекте. Печать неглубокая (читайте ниже).writable: false
для всех свойств с дескриптором данных). На доступное для записи свойство Setter не влияет (так как у него его нет). Замораживание является мелким : это означает, что если свойство является объектом, его свойства НЕ заморожены (если вы хотите, вы должны выполнить что-то вроде «глубокого замораживания», аналогично клонированию с глубоким копированием ). Используйте,Object.isFrozen(<yourObject>)
чтобы обнаружить это.Вам не нужно беспокоиться об этом, если вы напишите несколько забавных строк. Но если вы хотите написать код игры (как вы упомянули в связанном вопросе), вам следует позаботиться о хорошем дизайне. Попробуйте гуглить что-нибудь об антипаттернах и запахе кода . Это поможет вам избежать таких ситуаций, как «О, мне нужно полностью переписать мой код снова!» , это может сэкономить месяцы отчаяния, если вы хотите много кодировать. Удачи.
источник
function Product(name,price) { this.name = name; this.price = price; var _discount; // private member Object.defineProperty(this,"discount",{ get: function() { return _discount; }, set: function(value) { _discount = value; if(_discount>80) _discount = 80; } }); } var sneakers = new Product("Sneakers",20); sneakers.discount = 50; // 50, setter is called sneakers.discount+= 20; // 70, setter is called sneakers.discount+= 20; // 80, not 90! alert(sneakers.discount); // getter is called
get
это функция, которая вызывается при попытке прочитать значениеplayer.health
, как в:Это фактически не сильно отличается от:
Устанавливается противоположность get, которая будет использоваться при назначении значения. Поскольку сеттера нет, похоже, что присвоение здоровья игроку не предназначено:
Очень простой пример:
источник
()
для вызова ... Я не понимаю, в чем заключалась идея, когда они изобрели эту вещь. Функции абсолютно одинаковы: jsbin.com/bugipi/edit?js,console,outputdefineProperty - это метод для Object, который позволяет вам настраивать свойства в соответствии с некоторыми критериями. Вот простой пример с объектом сотрудника с двумя свойствами firstName и lastName и добавлением двух свойств путем переопределения метода toString для объекта.
Вы получите результат как: Jameel Moideen
Я собираюсь изменить тот же код с помощью defineProperty на объекте
Первый параметр - это имя объекта, а затем второй параметр - это имя добавляемого нами свойства, в нашем случае это toString, а затем последний параметр - это объект json, значение которого будет функцией и три записываемых параметра, перечислимые и настраиваемый. Прямо сейчас я просто объявил все как правда.
Если вы запустите пример, вы получите вывод: Jameel Moideen
Давайте разберемся, почему нам нужны три свойства: записываемое, перечисляемое и настраиваемое.
записываемый
Одна из самых раздражающих частей javascript - если вы измените свойство toString на что-то другое, например
если вы запустите это снова, все станет перерывом. Давайте изменим запись на ложь. Если запустить то же самое снова, вы получите правильный вывод как «Jameel Moideen». Это свойство предотвратит перезапись этого свойства позже.
перечислимый
если вы напечатаете все ключи внутри объекта, вы сможете увидеть все свойства, включая toString.
если вы установите enumerable в false, вы можете скрыть свойство toString от всех остальных. Если запустить это снова, вы получите firstName, lastName
конфигурируемый
если кто-то позже переопределит объект позже, например, перечислим в true и запустим его. Вы можете видеть, что свойство toString пришло снова.
Вы можете ограничить это поведение, установив настраиваемое значение false.
Первоначальная ссылка на эту информацию из моего личного блога
источник
По сути,
defineProperty
это метод, который принимает 3 параметра - объект, свойство и дескриптор. То, что происходит в этом конкретном вызове, - это"health"
свойствоplayer
объекта, которое назначается в 10 плюс 15 раз выше уровня объекта игрока.источник
да нет больше функции расширения для установки и получения это мой пример Object.defineProperty (obj, name, func)
источник
Object.defineProperty () - это глобальная функция. Она не доступна внутри функции, которая иначе объявляет объект. Вам придется использовать его статически ...
источник
Резюме:
Object.defineProperty
используется для создания нового свойства объекта player.Object.defineProperty
это функция, которая изначально присутствует в среде выполнения JS и принимает следующие аргументы:Object.defineProperty(obj, prop, descriptor)
Объект дескриптора является интересной частью. Здесь мы можем определить следующие вещи:
<boolean>
: еслиtrue
дескриптор свойства может быть изменен, а свойство может быть удалено из объекта. Если настраивается,false
дескриптор свойства, которые передаются,Object.defineProperty
не могут быть изменены.<boolean>
: еслиtrue
свойство может быть перезаписано с помощью оператора присваивания.<boolean>
: еслиtrue
свойство может быть повторено вfor...in
цикле. Также при использованииObject.keys
функции будет присутствовать клавиша. Если свойство имеет значение,false
они не будут повторяться с использованиемfor..in
цикла и не будут отображаться при использованииObject.keys
.<function>
: функция, которая вызывается всякий раз, когда требуется свойство. Вместо прямого значения эта функция вызывается, а возвращаемое значение задается как значение свойства.<function>
: функция, которая вызывается всякий раз, когда назначается свойство. Вместо установки прямого значения вызывается эта функция, а возвращаемое значение используется для установки значения свойства.Пример:
источник
источник
Определяет новое свойство непосредственно для объекта или изменяет существующее свойство для объекта и возвращает объект.
Простое объяснение определения свойства.
Пример кода: https://jsfiddle.net/manoj_antony32/pu5n61fs/
источник
источник