Почему константы не работают с объектами в JavaScript?

Недавно, с выходом ECMAScript 2015 было введено использование зарезервированного слова const, которое, как я понимаю, предназначено для констант.

Я пробовал это с некоторыми переменными, и все работает нормально, например:

'use strict';
const PI = 3.141516;
PI = 3.14;
console.log(PI);

, который возвращает следующую ошибку:

TypeError: Assignment to constant variable.

Это полностью ожидается в константе, но мои сомнения возникают, когда я делаю то же самое с объектом, например:

const empleado = {
  nombre: 'Juan',
  profesion: 'Programador'
};
empleado.nombre = 'Pedro';
console.log(empleado);

, который, к моему удивлению, возвращает объект с измененным узлом nombre, например:

{ nombre: 'Pedro', profesion: 'Programador' }

Вопрос

Разве я не должен выдавать ту же ошибку при попытке изменить объект, который был объявлен постоянным?

17
задан 20.01.2016, 17:15
5 ответов

Потому что ты путаешь концепцию постоянной ссылки с неизменным объектом.

Ссылка (в этом случае постоянная величина) - просто адрес памяти, которая указывает на объект. Взамен объект - стоимость, на которую ссылается постоянная величина.

В этом примере:

'use strict';
const empleado = {
    nombre: 'Juan',
    profesion: 'Programador'
};
empleado.nombre = 'Pedro';
console.log(empleado);

Стоимость постоянной величины empleado (ссылка, которая указывает на особенный объект) останься, не будучи изменен а именно продолжи указывать на тот же объект. То, что было изменено, является стоимостью empleado.nombre не empleado

Взамен:

'use strict';
const empleado = {
    nombre: 'Juan',
    profesion: 'Programador'
};
empleado = {
    nombre: 'Pedro',
    profesion: 'Hacker'
}; // Uncaught TypeError: Assignment to constant variable.
console.log(empleado);

Если он дает ошибку, потому что говорится о том, чтобы изменять стоимость постоянной величины empleado

Если ты хочешь сделать неизменный объект, ты должен использовать Object.freeze()

Пример:

'use strict';
var empleado = Object.freeze({
    nombre: 'Juan',
    profesion: 'Programador'
});
//empleado.nombre = 'Pedro'; // TypeError: Cannot assign to read only property 'nombre' of #<Object>
empleado = {
    nombre: 'Pedro',
    profesion: 'Hacker'
};

Этот раз уже не позволено изменять объект, на который ссылается переменная empleado, но если ты сможешь изменять переменную empleado так как он не является постоянным.

Из-за Вашего места ты можешь сочетать обе вещи

'use strict';
const empleado = Object.freeze({
    nombre: 'Juan',
    profesion: 'Programador'
});
//empleado.nombre = 'Pedro'; // TypeError: Cannot assign to read only property 'nombre' of #<Object>
//empleado = {
//    nombre: 'Pedro',
//    profesion: 'Hacker'
//}; // Uncaught TypeError: Assignment to constant variable.

Таким образом, ты способствовал бы тому, чтобы ты не смог менять ссылку на объект и также Ваши свойства.

Больше информации о постоянных величинах в языке сценариев JavaScript в этом ответе на вопрос Преимуществ в том, чтобы использовать const на var в языке сценариев JavaScript

18
ответ дан 24.11.2019, 14:58
  • 1
    Для меня, он iló gico думать, что, если изменил член объекта, я не изменяю объект. –  Máxima Alekz 04.03.2019, 18:22
  • 2
    @Má ximaAlekz тогда ты не понял основательно, как хранится стоимость ссылкой в памяти. Стоимость (на уровне памяти) переменной, которая хранит объект из-за ссылки (Array, Function, Object), не объект в sí сам а direcció n (виртуальной) памяти, где находится объект. Это эта direcció n памяти, которая постоянная не объект, на который указывает ссылка. –  Carlos Muñoz 04.03.2019, 19:43

Заявление const верьте в ссылку одинокого чтение в стоимость. Это не означает, что стоимость, которую он хранит, - неизменная, одинокий, что идентификатор переменной не может быть повторно распределенным

Это означает, что ты не можешь sobreescribir объект:

'use strict';
const empleado = {
  nombre: 'Juan',
  profesion: 'Programador'
};
empleado = {"atributo": "valor"}

Потому что он помечает тебя TypeError: Assignment to constant variable.

Однако, признаки объектов не защищены. Так что, как в твоем примере, этом решении ты можешь выполнять ее без проблем:

empleado.nombre = 'Pedro';

Если ты хочешь считать объект полностью постоянным, ты можешь использовать следующую функцию:

 var constantize = (obj) => {
  Object.freeze(obj);
  Object.keys(obj).forEach( (key, value) => {
    if ( typeof obj[key] === 'object' ) {
      constantize( obj[key] );
    }
  });
};

В твоем примере он остался бы, таким образом:

'use strict';
 var empleado = {
   nombre: 'Juan',
   profesion: 'Programador'
 };
constantize(empleado);
empleado.nombre = "Pedro"; // Marcará un error, se encuentra protegida.

Для большей информации ты можешь видеть (на английском):

16
ответ дан 24.11.2019, 14:58
  • 1
    Очень хороший ответ, это был dif и # 237; cil decisi и # 243; n принимать одну, однако оба я пошли очень и #250; tiles. Спасибо. –  Gepser 20.01.2016, 18:32

В нескольких документациях уже он приходит объясненный, что не возможно делать это с переменными:

const PI = 3.141592653589793;
PI = 3.14;      // ERROR
PI = PI + 10;   // ERROR

, Но sГ - возможно делать это с arrays:

// Puedes crear un array como constante
const frutas = ["Pera", "Uva", "Naranja"];

// También puedes modificar uno de sus valores
frutas[0] = "Manzana";

// Y puedes añadirle elementos
frutas.push("Platano");

Но не это:

const fruta = ["Manzana", "Pera", "Naranja"];
cars = ["Platano", "Uva", "Melocoton"];    // ERROR
1
ответ дан 24.11.2019, 14:58

Когда ты помечаешь что-то как постоянная величина не estГЎs способствуя тому, чтобы в объект не было возможно изменять ему стоимость, но снопы что указатели переменной не varГ - в, где они обозначаются. Однако, ты можешь давать другую стоимость в памяти этим переменным, всякий раз когда не varГ - и место памяти в, тот, который estГЎn хранения.

Пример: Если ты производишь Первый постоянный так называемый объект с двумя переменными A1 и B1, и другой так называемой Секундой с переменными A2 и B2. Если ты выравниваешь их и делаешь "Сначала = Секунда", действительно estГЎs изменено указатели A1 и B1 в A2 и B2 соответственно, и он поэтому а следовательно он отпускает ее тебе excepciГіn. Однако ты можешь setear A1 в стоимость A2 без проблемы, потому что estarГЎs меняя стоимость в память указателя Сначала. A1, но не указатель в sГ - сам.

1
ответ дан 24.11.2019, 14:58

Чтобы давать ему более гипотетический взгляд этому старому вопросу. Давайте предполагать, что const объявляет неизменные постоянные величины как ждет OP.

ВїQue ocurrirГ - в со следующим cГіdigo?

var empleado = {
  nombre: 'Juan',
  profesion: 'Programador'
};

const e = empleado; //crearia esto un clon inmutable?
                    //o haria que el objeto original fuese inmutable?

empleado.nombre = 'Pedro'; //error?

console.log(empleado); //juan o pedro?
console.log(e); //definitivamente pedro, no?

Конечно правильный ответ проще:

var , let и const объявляют идентификаторов из переменных или постоянных величин. Не думайте, что ни объекты ни примитивная стоимость это не происходит правой стороны =.

И, просвет estГЎ, const он относится к тому, что постоянным является идентификатор, не объект, ассоциируемый с этим.

1
ответ дан 24.11.2019, 14:58

Теги

Похожие вопросы