Книга: JavaScript. Подробное руководство, 6-е издание
6.6. Методы чтения и записи свойств
6.6. Методы чтения и записи свойств
Выше уже говорилось, что свойство объекта имеет имя, значение и набор атрибутов. В ECMAScript 5[10]
значение может замещаться одним или двумя методами, известными как методы чтения (getter
) и записи (setter
). Свойства, для которых определяются методы чтения и записи, иногда называют свойствами с методами доступа, чтобы отличать их от свойств с данными, представляющих простое значение.
Когда программа пытается получить значение свойства с методами доступа, интерпретатор вызывает метод чтения (без аргументов). Возвращаемое этим методом значение становится значением выражения обращения к свойству. Когда программа пытается записать значение в свойство, интерпретатор вызывает метод записи, передавая ему значение, находящее справа от оператора присваивания. Этот метод отвечает за «установку» значения свойства. Значение, возвращаемое методом записи, игнорируется.
В отличие от свойств с данными, свойства с методами доступа не имеют атрибута writable
. Если свойство имеет оба метода, чтения и записи, оно доступно для чтения/записи. Если свойство имеет только метод чтения, оно доступно только для чтения. А если свойство имеет только метод записи, оно доступно только для записи (такое невозможно для свойств с данными) и попытки прочитать значение такого свойства всегда будут возвращать undefined
.
Самый простой способ определить свойство с методами доступа заключается в использовании расширенного синтаксиса определения литералов объектов:
var о = {
// Обычное свойство с данными
data_prop: value,
// Свойство с методами доступа определяется как пара функций
get accessor_prop() { /* тело функции */ },
set accessor_prop(value) { /* тело функции */ }
};
Свойства с методами доступа определяются как одна или две функции, имена которых совпадают с именем свойства и с заменой ключевого слова function
на ge
t и/или set
. Обратите внимание, что не требуется использовать двоеточие для отделения имени свойства от функции, управляющей доступом к свойству, но по-прежнему необходимо использовать запятую после тела функции, чтобы отделить метод от других методов или свойств с данными. Для примера рассмотрим следующий объект, представляющий Декартовы координаты точки на плоскости. Для представления координат X и Y в нем имеются обычные свойства с данными, а также свойства с методами доступа, позволяющие получить эквивалентные полярные координаты точки:
var р = {
// х и у - обычные свойства с данными, доступные для чтения/записи.
х: 1.0,
у: 1.0,
//r - доступное для чтения/записи свойство с двумя методами доступа.
// Не забывайте добавлять запятые после методов доступа,
get r() { return Math.sqrt(this.x*this.x + this.y*this.y); },
set r(newvalue) {
var oldvalue = Math.sqrt(this.x*this.x + this.y*this.y);
var ratio = newvalue/oldvalue;
this.x *= ratio;
this.у *= ratio;
}
// theta - доступное только для чтения свойство с единственным методом чтения,
get theta() { return Math.atan2(this.у, this.x); }
};
Обратите внимание на использование ключевого слова this
в методах чтения и записи выше. Интерпретатор будет вызывать эти функции, как методы объекта, в котором они определены, т.е. в теле функции this
будет ссылаться на объект точки. Благодаря этому метод чтения свойства r может ссылаться на свойства x и у, как this.x
и this.у
. Подробнее о методах и ключевом слове this
рассказывается в разделе 8.2.2.
Свойства с методами доступа наследуются так же, как обычные свойства с данными, поэтому объект р
, определенный выше, можно использовать как прототип для других объектов точек. В новых объектах можно определять собственные свойства х и у, и они будут наследовать свойства r
и theta
:
var q = inherit(p); // Создать новый объект, наследующий методы доступа
q.x = 1; q.y = 1; // Создать собственные свойства с данными в объекте q
console.log(q.r); // И использовать унаследованные свойства
console.log(q.theta); // с методами доступа
Фрагмент выше использует свойства с методами доступа для определения API, обеспечивающего представление единого набора данных в двух системах координат (Декартовой и полярной). Еще одной причиной использования свойств с методами доступа может быть необходимость проверки значения перед записью и возврат разных значений при каждом чтении свойства:
// Этот объект генерирует последовательность увеличивающихся чисел
var serialnum = {
// Это свойство с данными хранит следующее число в последовательности.
// Знак $ в имени свойства говорит о том, что оно является частным.
$n: 0,
// Возвращает текущее значение и увеличивает его
get next() { return this.$n++; },
// Устанавливает новое значение n, но только если оно больше текущего
set next(n) {
if (n >= this.Sn) this.$n = n;
else throw "число может быть только увеличено ";
}
};
Наконец, ниже приводится еще один пример использования метода чтения для реализации свойства с «таинственным» поведением.
// Этот объект имеет свойства с методами доступа, при обращении к которым возвращаются
// случайные числа. Например, каждый раз при вычислении выражения ”random.octet"
// будет возвращаться случайное число в диапазоне от 0 до 255.
var random = {
get octet() { return Math.floor(Math.random()*256); },
get uint16() { return Math.floor(Math.random()*65536); },
get int16() { return Math.floor(Math.random()*65536)-32768; }
};
В этом разделе было показано, как определять свойства с методами доступа при создании нового объекта с помощью литерала. В следующем разделе будет показано, как добавлять свойства с методами доступа в существующие объекты.
- Доступ к свойствам файла
- Свойства
- Инкапсуляция на основе методов чтения и модификации
- 6.7. Атрибуты свойств
- Свойства, доступные только для чтения, и свойства, доступные только для записи
- Индексные свойства
- 6.2.3. Ошибки доступа к свойствам
- 6.7.1. Устаревшие приемы работы с методами чтения и записи
- 10.3.1. Свойства RegExp
- 11.2. СВОЙСТВА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
- 4. Свойства унарных операций
- 3. Свойства бинарных операций