Метод Object.defineProperty - позволяет устанавливать свойствам некоторые настройки (можно ли свойство изменять, удалять и др.)
См. также Object.defineProperties.
Синтаксис
Object.defineProperty(объект, 'имя свойства', дескриптор);
Дескриптор - это объект, который описывает поведение свойства. В нем могут быть следующие свойства (в скобках указаны значения по умолчанию):
value //значение свойства (undefined)
writable //если true - свойство можно перезаписывать (false)
configurable // если true, то свойство можно удалять (false)
enumerable //если true, то свойство видно в цикле for..in (false)
get //Функции, которая возвращает значение свойства (undefined)
set //Функции, которая записывает значение свойства (undefined);
Если со свойством произвести запрещенное действие, например, попытаться изменить в то время как writable = false, то ничего не произойдет (а в строгом режиме (при указании 'use strict') - будет ошибка). Также запрещено указывать value/writeble если указаны get/set.
Примеры
Пример
Свойство созданное обычным способом не имеет никаких необычных свойств - его можно перезаписывать, удалять и одно видно в for..in. Давайте создадим свойство, которое нельзя удалять:
var obj = {
val1: 10, //Обычное свойство
}
//Создадим свойство через defineProperty
Object.defineProperty(obj, 'val2', {
value: 10,
configurable: false //нельзя удалять
});
alert(obj.val1) //10
alert(obj.val2) //10
delete obj.val1
delete obj.val2
alert(obj.val1) //undefined
alert(obj.val2) //10
В данном примере свойство val1 создано обычным способом, и после удаления - оно удалилось. Но val2 запрещено удалять, поэтому оно осталось.
Пример
Создадим свойство, которое не видно через for..in:
var obj = {
val1: 10, //Обычное свойство
name: 'user',
}
Object.defineProperty(obj, 'val2', {
value: 20,
enumerable: false //не видно в for..in
});
for (var key in obj) {
document.write('obj.' + key + ': ' + obj[key] + '<br>');
}
document.write('<hr>obj.val2: ' + obj.val2); //выводим val2 после цикла
В данном примере циклом for..in были выведены все свойства объекта, но не смотря на это val2 выведен не был, хотя он в объекте и есть.
Результат выполнения кода:
obj.name: user
obj.val2: 20
Пример
В данном примере создадим объект квадрата со свойствами: ширина и периметр. При этом значение периметру явно указывать не будем, оно будет определятся на основании ширины:
var square = {
size: 5,
}
Object.defineProperty(square, 'p', {
get: function() {
return this.size * 4;
},
set: function(p)
{
this.size = p / 4;
}
});
alert(square.size) //5
alert(square.p) //20
square.size = 10;
alert(square.size) //10
alert(square.p) //40
square.p = 100
alert(square.size) //25
alert(square.p) //100
В этом примере было создано свойство 'p' значение которого всегда равно size * 4. Вначале 'size' было равно 5, а 'p' - 20. Затем мы изменили только 'size', но и 'p' поменялось тоже. Таким образом можно создавать свойства, которые могут возвращать и устанавливать значение по определенной функции.