касиеттери - геттер жана сеттер
касиеттери - геттер жана сеттер
Объекттин касиеттеринин эки түрү бар.
Биринчи түрү маалымат касиеттери болуп саналат . Биз алар менен кантип иштөөнү билебиз. Биз буга чейин колдонгон бардык касиеттер маалымат касиеттери болгон.
Экинчи типтеги мүлктөрдү азырынча карай элекпиз. Бул аксессуар касиеттери . Негизинен булар маанини коюу жана алуу үчүн колдонулган функциялар, бирок тышкы коддо алар кадимки объект касиеттерине окшош.
Аксессорлордун касиеттери методдор менен көрсөтүлөт: "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@
Эми эски код да иштейт жана бизде сонун кошумча функция бар!