Создание неизменяемого свойства объекта посредством переназначения, но изменяемого в JavaScript

#javascript #properties #getter-setter #unmodifiable

#javascript #свойства #средство получения-установки #неизменяемый

Вопрос:

 class Hero extends Character {
constructor (name, race, gender, role, level){
    super(name, race, gender, role, level);
    this.inventory = [];
    this.experience = {
        experienceNeeded: 100,
        experienceObtained: 0
    };
    this.gold = 0;
}
  

У меня есть этот класс, который определяет, каким будет персонаж игрока. Я хочу сделать оба experienceObtained и gold свойства неизменяемыми с помощью переназначения, но изменяемыми с помощью операторов, чтобы пользователи не устанавливали свои собственные значения для этих свойств с помощью консоли.

 this.gold = {
        amount: 0,
        get gold(){
            return this.amount;
        }
    };
  

Как показано выше, я пытался использовать средство получения без объявления средства установки, но я все еще могу присвоить amount любое значение через консоль.

Я не знаю, неправильно ли я понимаю использование геттеров и установщиков в JavaScript или это невозможно сделать.

Комментарии:

1. Вы мало что можете сделать для защиты от изменений ваших данных на стороне клиента. Браузер, в конечном счете, принадлежит пользователю.

Ответ №1:

чтобы пользователи не устанавливали свои собственные значения для этих свойств с помощью консоли.

Самый простой способ сделать это — просто запретить доступ к экземпляру Hero с верхнего уровня — например, обернуть все в IIFE:

 (() => {
  const hero = new Hero();
  // do stuff with hero
})();
  

Тогда все, что вы делаете внутри IIFE, будет номинально закрытым — пользователь не сможет зайти в консоль, ссылаться и изменять то, что он хочет. (Тем не менее, поскольку это их браузер, они могли бы сделать это другими способами, например, с помощью пользовательского скрипта — вы не можете доверять тому, что все, что выполняется на компьютере клиента, выполняется законно.)

Используя аналогичный метод, полагаясь на номинальную конфиденциальность замыкания, вы можете создать amount средство получения переменной замыкания без средства установки, гарантируя, что это amount невозможно изменить извне (если, конечно, не изменен исходный код, в этом случае все ставки в любом случае отменяются):

 const Hero = (() => {
  const privateHeroGold = new WeakMap();
  return class Hero {
    constructor() {
      privateHeroGold.set(this, 0);
    }
    get gold() {
      return privateHeroGold.get(this);
    }
    set gold(g) {
      console.log("You're not allowed to do that!");
    }
  }
})();
const hero = new Hero();
console.log(hero.gold);
hero.gold = 5;
console.log(hero.gold);  

Комментарии:

1. Не сделает ли это hero.gold неизменяемым с помощью операторов, если я использую функцию для изменения и добавления значения, используя что-то вроде hero.gold = 1 позже?

2. Вы можете поместить всю логику, которая изменяет значение, внутрь замыкания , используя WeakMap.