Loading...

касиеттери - геттер жана сеттер

касиеттери - геттер жана сеттер

 

Объекттин касиеттеринин эки түрү бар.

Биринчи түрү маалымат касиеттери болуп саналат . Биз алар менен кантип иштөөнү билебиз. Биз буга чейин колдонгон бардык касиеттер маалымат касиеттери болгон.

Экинчи типтеги мүлктөрдү азырынча карай элекпиз. Бул аксессуар касиеттери . Негизинен булар маанини коюу жана алуу үчүн колдонулган функциялар, бирок тышкы коддо алар кадимки объект касиеттерине окшош.

Алуучу жана орнотуучулар

Аксессорлордун касиеттери методдор менен көрсөтүлөт: "getter" - окуу үчүн жана "setter" - жазуу үчүн. Объект литерал деп жарыяланганда, алар getжана менен белгиленет set:

@A@let obj = {
  get propName() {
    // геттер, срабатывает при чтении obj.propName
  },

  set propName(value) {
    // сеттер, срабатывает при записи obj.propName = value
  }
};@A@

Окулганда алуучу obj.propName, баа берилгенде орнотулган.

Мисалы, бизде userкасиеттери бар объект бар nameжана surname:

@A@let user = {
  name: "John",
  surname: "Smith"
};@A@

Эми толук квалификациялуу ат үчүн объект касиетин кошолу fullName, ал биздин учурда "John Smith". Албетте, биз буга чейин болгон маалыматты кайталагыбыз келбейт, андыктан аны аксессуар менен ишке ашырабыз:

@A@let user = {
  name: "John",
  surname: "Smith",

  get fullName() {
    return `${this.name} ${this.surname}`;
  }
};

alert(user.fullName); // John Smith@A@

Сыртынан караганда, аксессуар касиети кадимки мүлккө окшош. Бул аксессуар касиеттеринин пункту. Биз аны user.fullName функция деп атабайбыз, бирок аны кадимки касиет катары окуйбуз: алуучу көшөгө артындагы бардык ишти аткарат.

Учурда бизде fullNameалуучу гана бар. Эгерде биз дайындоого аракет кылсак user.fullName=, ката пайда болот:

@A@let user = {
  get fullName() {
    return `...`;
  }
};

user.fullName = "Тест"; // Ошибка (у свойства есть только геттер)@A@

Келгиле, муну жөндөөчү кошуу менен оңдойлу user.fullName:

@A@let user = {
  name: "John",
  surname: "Smith",

  get fullName() {
    return `${this.name} ${this.surname}`;
  },

  set fullName(value) {
    [this.name, this.surname] = value.split(" ");
  }
};

// set fullName запустится с данным значением
user.fullName = "Alice Cooper";

alert(user.name); // Alice
alert(user.surname); // Cooper@A@

Натыйжада, биз "виртуалдык" менчикке ээ болдук fullName. Аны окууга жана өзгөртүүгө болот.

Менчик дескрипторлоруна кириңиз

Аксессор касиетинин дескрипторлору "кадимки" маалымат касиеттеринен айырмаланат.

valueАксессорлордун касиеттери жана дегенге ээ эмес writable, анын ордуна getжана функцияларын сунуштайт set.

Башкача айтканда, аксессуар туткасы төмөнкүлөргө ээ болушу мүмкүн:

  • get– касиетти окуганда иштей турган аргументсиз функция,
  • set- касиет ыйгарылганда чакырылган бир аргументти алган функция;
  • enumerable- маалымат касиеттери менен бирдей,
  • configurable– маалымат касиеттери менен бирдей.

fullNameМисалы, колдонуучу аксессуарды түзүү үчүн, definePropertyбиз тутканы getжана аркылуу өткөрө алабыз set:

@A@let user = {
  name: "John",
  surname: "Smith"
};

Object.defineProperty(user, 'fullName', {
  get() {
    return `${this.name} ${this.surname}`;
  },

  set(value) {
    [this.name, this.surname] = value.split(" ");
  }
});

alert(user.fullName); // John Smith

for(let key in user) alert(key); // name, surname@A@

Дагы бир жолу көңүл буруңуз, объект касиети же аксессуар касиети (методдор менен get/set) же маалымат касиети (маани менен value) болушу мүмкүн.

getЭгерде сиз экөөнү тең жана valueбир эле дескриптордо көрсөтүүгө аракет кылсаңыз , ката пайда болот

@A@// Error: Invalid property descriptor.
Object.defineProperty({}, 'prop', {
  get() {
    return 1
  },

  value: 2
});@A@

Акылдуу алуучулар/жөндөөчүлөр

Алуучулар/жөндөөчүлөр "чыныгы" менчик баалуулуктарынын үстүнөн оролгондор катары колдонулушу мүмкүн, алар кантип башкарыларын көбүрөөк көзөмөлдөөгө мүмкүнчүлүк берет.

Мисалы, эгер биз үчүн кыска аталышты коюуну алдын алгыбыз келсе user, биз текшерүү үчүн орнотуучуну колдонсок болот nameжана маанинин өзүн өзүнчө касиетте сактай алабыз _name:

@A@let user = {
  get name() {
    return this._name;
  },

  set name(value) {
    if (value.length < 4) {
      alert("Имя слишком короткое, должно быть более 4 символов");
      return;
    }
    this._name = value;
  }
};

user.name = "Pete";
alert(user.name); // Pete

user.name = ""; // Имя слишком короткое...@A@

Ошентип, аталыштын өзү ичинде сакталат _name, ага алуучу жана орнотуучу аркылуу кирүүгө болот.

Техникалык жактан алганда, тышкы код дагы эле ат менен түз кире алат , бирок менен башталган касиеттер ички жана объекттин сыртынан кирүүгө болбойт user._nameдеген белгилүү конвенция бар ."_"

Шайкештик үчүн колдонуңуз

Аксессорлордун кызыктуу чөйрөсү бар - алар каалаган убакта "нормалдуу" касиетти алып, анын жүрүм-турумун гетер жана сетерге өзгөртүү менен өзгөртүүгө мүмкүндүк берет.

Мисалы, биз userаталыш nameжана жаш маалымат касиеттерин колдонуу менен объектти ишке ашыра баштадык дейли age:

@A@function User(name, age) {
  this.name = name;
  this.age = age;
}

let john = new User("John", 25);

alert( john.age ); // 25@A@
…Бирок эртеби-кечпи баары өзгөрүшү мүмкүн. Жаштын ордуна, ageбиз туулган күндү сактоону чечсек болот birthday, анткени бул так жана ыңгайлуу:
@A@function User(name, birthday) {
  this.name = name;
  this.birthday = birthday;
}

let john = new User("John", new Date(1992, 6, 1));@A@

Менчикти колдонгон эски код менен эмне кылабыз age?

Биз мындай жерлердин баарын таап, аларды өзгөртүүгө аракет кылсак болот, бирок бул көп убакытты талап кылат жана кодду башка адамдар колдонсо, ишке ашпай калышы мүмкүн. Мындан тышкары, ageбул үчүн мыкты мүлк user, туурабы?

Аны сактап калалы.

үчүн алуучуну кошуу ageкөйгөйдү чечет:

@A@function User(name, birthday) {
  this.name = name;
  this.birthday = birthday;

  // возраст рассчитывается из текущей даты и дня рождения
  Object.defineProperty(this, "age", {
    get() {
      let todayYear = new Date().getFullYear();
      return todayYear - this.birthday.getFullYear();
    }
  });
}

let john = new User("John", new Date(1992, 6, 1));

alert( john.birthday ); // доступен как день рождения
alert( john.age );      // ...так и возраст@A@

Эми эски код да иштейт жана бизде сонун кошумча функция бар!