Как предотвратить изменение параметров конструктора

#javascript #class

Вопрос:

У меня есть class File конструктор и, который принимает fullname параметр. Как я могу предотвратить это изменение? Я пробовал это с сеттером и геттером, но это не работает

 class File {
  constructor(fullName) {
    this.fullName = fullName;
  }
  get fullname() {
    return this.fullname;
  }
  set fullname(newValue) {
    if (newValue) {
      newValue = this.fullName;
    }
  }

}

let example = new File("example.txt");
example.fullName = "modified.txt";
console.log(example.fullName); // should be example.txt 

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

1. Опечатка : return this.fullName

2. не связано с проблемой, но внутри сеттера: newValue = this.fullName; —> > this.fullName = newValue; и вам нужно исправить имя сеттера: fullname —> > fullName . Также переименуйте геттер.

3. @TusharShahi, @Yousaf: Это не очень помогло бы, потому что геттер/сеттер fullname не запускается при доступе fullName .

4. @FelixKling правильно; Я предложил оператору исправить имя сеттера.

Ответ №1:

Вы можете создать свойство только для чтения с помощью Object.defineProperty :

 class File {
  constructor(fullName) {
    Object.defineProperty(this, 'fullName', {
      enumerable: true,
      writable: false, // not necessary (because default) but more explicit,
      value: fullName,
    });
  }
}


let example = new File("example.txt");
example.fullName = "modified.txt";
console.log(example.fullName); 

Обратите внимание, что присвоение свойства приведет к ошибке в строгом режиме.


Если вы хотите быть в строгом режиме, но также хотите молча игнорировать назначение, вы можете воспользоваться этим getter/setter подходом, но вам все равно придется хранить реальное значение где-то на объекте, а это означает, что к нему все еще можно получить доступ и изменить, если знать, к какому свойству обращаться.~ но это немного более развито. Вы бы в основном создали средство получения и настройки для каждого экземпляра, тем самым избежав необходимости хранить исходное значение в самом объекте:

 "use strict";

class File {
  constructor(fullName) {
    Object.defineProperty(this, 'fullName', {
      enumerable: true,
      set: value => {}, // ignore
      get: () => fullName,
    });
  }
}


let example = new File("example.txt");
example.fullName = "modified.txt";
console.log(example.fullName); 

Частные свойства, которые являются относительно новой функцией JavaScript, могут сделать это немного «приятнее» (субъективно):

 class File {
  #fullName;
  
  constructor(fullName) {
    this.#fullName = fullName;
  }
  get fullName() {
    return this.#fullName;
  }
  set fullName(newValue) {
    // ignore new value
  }

}

let example = new File("example.txt");
example.fullName = "modified.txt";
console.log(example.fullName); 

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

1. Использование частных свойств помогло мне, но я задаюсь вопросом, почему у меня ошибка Cannot assign to read only property 'fullName' of object '#<File> в первом методе? Спасибо за помощь

2. Ах, когда вы находитесь в строгом режиме, попытка присвоить свойство только для чтения выдает ошибку вместо того, чтобы молча игнорировать ее.

Ответ №2:

Использование синтаксиса ES2020 :

 class File {
  #fullName = null;
  
  constructor(fullName) {
    this.fullName = fullName;
  }
  
  get fullName() {
    return this.#fullName;
  }
  
  set fullName(newValue) {
    this.#fullName ??= newValue;
  }
}

let example = new File("example.txt");
example.fullName = "modified.txt";
console.log(example.fullName); // should be example.txt 

Есть несколько мест , в которых вы написали fullName с fullname ошибкой, обратите внимание на случаи, когда это важно в JavaScript.

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

1. FWIW, частная собственность не является частью ES6. Я думаю, что они были частью выпуска этого года?

2. @FelixKling Да, спасибо, что указал. class Ключевое слово является частью синтаксиса ES6, но личные поля и логическое присвоение ??= значения null появились намного позже.