Перезапись неперезаписываемых свойств объекта

Почему, определив атрибут writable свойства в объекте как false, я все-равно могу изменить это свойство?

var person = {
	age: "30",
	name: "Evgeniy"
};

Object.defineProperty(person, "gender", {
	value: 'male',
	writable: false,
	enumerable: false,
	configurable: false
});

console.log(Object.getOwnPropertyDescriptor(person, 'gender'));
console.log(person.gender = 'female');


Кратко: на самом деле не можешь.

Полно
Наверное ты думаешь что значение поля изменилось потому что этот console.log выводит значение "female" в консоль. На самом деле значение свойства gender не именилась. В консоли ты увидел результат вычисления выражения person.gender = 'female'. Чтобы проверить изменилось ли значение свойства, надо еще раз залогировать person.gender, и ты увидишь что оно не изменилось.

Все равно остается открытым вопрос в том как браузер позволяет коду, который по определению (запись значения в свойство, в которое запись запрещена) не должен выполняться. В нестрогом режиме браузер игнорирует результаты этой операции, но продолжает выполнять код без ошибок. А в строгом режиме подобный код упадет с ошибкой. Ниже пример кода где тот же код падает в строгом режиме.

;(function () {
	'use strict'

	var person = {
		age: "30",
		name: "Evgeniy"
	};

	Object.defineProperty(person, "gender", {
		value: 'male',
		writable: false,
		enumerable: false,
		configurable: false
	});

	console.log(Object.getOwnPropertyDescriptor(person, 'gender'));
	console.log(person.gender = 'female');
}())
1 лайк

Теперь все ясно, спасибо.

Еще вопрос, а если я запрещу любые действия по изменению объекта, скажем методом .freeze() я уже никак на странице не смогу отменить его заморозку и изменять его свойства? Если не смогу, то можно ведь скопировать объект каким-то образом и работать уже с его копией?

После freeze обратного пути нет. Только создавать копию.

Кстати, freeze, не влияет на вложенные свойства. Он влияет только на непосредственный свойства объекта.