Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Задать значение переменной, а потом запретить ее перезаписывать (https://javascript.ru/forum/misc/65744-zadat-znachenie-peremennojj-potom-zapretit-ee-perezapisyvat.html)

SvetozarPNZ 05.11.2016 22:42

Задать значение переменной, а потом запретить ее перезаписывать
 
var deck = (function(){
	var massOfCards = [];

        // здесь заполняем массив

	return massOfCards;	//Ошибка!
})();

Object.defineProperty(window, "deck", {
	writable: false,
	configurable: false,
});


Мне показывает ошибку, нельзя присваивать значение свойству read only. Без выкрутасов с Object.defineProperty все работает.
В чем подвох? Object.defineProperty выполняется заранее?
Если да, то как лучше реализовать задачу?

Aetae 05.11.2016 22:49

"defineProperty", он декларирует свойство, а не устанавливает флаги:
Object.defineProperty(window, "deck", {
    writable: false,
    configurable: false,
    value: (function(){
        var massOfCards = [];
     
            // здесь заполняем массив
     
        return massOfCards;
    })()
});
Если пользуетесь современным javascript, то можно и так:
const deck = (function(){
    var massOfCards = [];
 
        // здесь заполняем массив
 
    return massOfCards; //Ошибка!
})();


Только одна мелочь: содержимое массива всё равно вы сможете менять, защищаете от перезаписи вы только саму переменную.

SvetozarPNZ 05.11.2016 22:57

Цитата:

Сообщение от Aetae (Сообщение 434163)
Только одна мелочь: содержимое массива всё равно вы сможете менять, защищаете от перезаписи вы только саму переменную.

Спасибо. Получается в первую очередь сработал defineProperty.

Чтобы решить "мелочь", нужно в цикле аналогично продекларировать каждое свойство (элемент)?

Aetae 05.11.2016 23:09

Цитата:

Сообщение от SvetozarPNZ (Сообщение 434165)
Чтобы решить "мелочь", нужно в цикле аналогично продекларировать каждое свойство (элемент)?

Для объектов(в js масивы тоже объекты) есть "Object.freeze()". Т.е.:
const deck = (function(){
    var massOfCards = [];
  
        // здесь заполняем массив
  
    return Object.freeze(massOfCards); 
})();

Но следует помнить, что каждый вложенный объект придётся замораживать отдельно.

P.S. Вообще в js практически нет задач где действительно бы стоило морозить значения.

fuckingquest 06.11.2016 01:20

Цитата:

Сообщение от Aetae
"defineProperty", он декларирует свойство, а не устанавливает флаги:

Судя по поведению, если св-во уже существует, он просто установит флаги уже существующему св-ву, поэтому, таки, устанавливает флаги.

fuckingquest 06.11.2016 01:23

SvetozarPNZ,
У вас нет ошибки там где Вы показали, все нормально работает. У Вас ошибка возникает при попытке присваивания где то ниже, скорей всего

Aetae 06.11.2016 01:31

fuckingquest, хз хз, надо спеку смотреть. Ибо по описанию - значение value по умолчанию должно быть undefined. То что это работает, ещё ничего не значит.)

fuckingquest 06.11.2016 01:40

Aetae,
то что я нашел, говорит об обратном:

Функция defineProperty применяется для добавления нового собственного свойства и/или добавления атрибутов уже существующего собственного свойства объекта.

http://es5.javascript.ru/x15.2.html#x15.2.3.6

Aetae 06.11.2016 01:54

fuckingquest, ок. MDN не так ясно об этом говорит. Всё же define - это define, потому вводит в заблуждение.)

fuckingquest 06.11.2016 02:38

Aetae,
это о многом можно сказать, вообще характерно для синт. сахара современных ЯП. Например выражение function(){}, на самом деле, адекватно бы выглядело как f = function create; f.setArguments() f.setBody(); f.setLexicalEnvironment()
я уж не говорю о function declaration

касаемо define, кстати, оператор присваивания в JS выполняет роль и define(определения) и set(присваивания)

Слишком много подковерной возни в современных ЯП, это проблема


Часовой пояс GMT +3, время: 10:30.