Метод 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.val1: 10
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' поменялось тоже. Таким образом можно создавать свойства, которые могут возвращать и устанавливать значение по определенной функции.