Почему константы считаются изменяемыми в Javascript, когда только частично верно? - PullRequest
0 голосов
/ 05 марта 2019

В Javascript, как указано в документации MDN :

Объявление const создает доступную только для чтения ссылку на значение.Это не означает, что значение, которое оно содержит, является неизменным, просто то, что идентификатор переменной не может быть переназначен.Например, в случае, когда содержимое является объектом, это означает, что содержимое объекта (например, его свойства) может быть изменено

Однако попытка изменить строку или число приведет к ошибкекак TypeError: invalid assignment to const.Если это так, почему const не рассматривается как изменяемый в любом сценарии, где const является значением, отличным от массива или объекта?

Ответы [ 2 ]

0 голосов
/ 05 марта 2019

Однако попытка изменить строку или число приведет к ошибке как TypeError: invalid assignment to const

Это именно то, что сказано в документации - идентификатор переменной не может быть переназначен .

Идентификатор const всегда будет указывать на одно и то же место.Однако содержимое этого места может измениться.

Если это место является объектом, его можно изменить несколькими способами (Object.prototype.assign, ключевое слово delete, присвоение свойства).Для примитивных типов просто нет способа разыменовать («захватить») содержимое, кроме как путем изменения их идентификаторов (что недопустимо для const).Вот почему постоянные примитивы являются неизменными, а постоянные объекты - нет.

0 голосов
/ 05 марта 2019

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

Понимание указателей

В некоторых языках программирования существует понятие указателя.Указатель - это переменная, содержащая адрес другого указателя.Поэтому в языке, подобном c, const, доступный только для чтения и изменяемый, более очевиден:

#include <stdio.h>
int main(){
    const int counter = 0;
    *(int *)&counter = 39;
    printf("%d", counter);
}

В приведенном выше коде C мы создаем ссылку только на чтение на 0. Однако, используя указатели, мы приводимзначение, указывающее на счетчик, а затем снова укажите на это значение.Счетчик не будет рассматривать это как изменение значения напрямую.Итак, мы видим, что на языке, использующем указатели, такой код можно сделать.

Однако возникает вопрос, а как насчет Javascript, где нет понятия указателя?Возможно, const в ситуации, отличной от Object, или Array следует считать неизменным.

Javascript как прототипический язык

Затем он переходит к следующему пункту.Javascript - это прототип языка.Это означает, что все в Javascript в конечном итоге представлено объектами, строящимися друг от друга.Учитывая все эти знания, все, что нам нужно сделать, - это сканировать документ или окно AKA с наивысшим доступным объектом.

Использование наших знаний об указателях и прототипах

Следовательно, можно предположить, что даже значение только для чтения, такое const в Javascript, теоретически должно иметь вид мутации.Итак, вопрос в том, как можно пойти дальше и сделать это?

Пример кода - Mutating Const

const test = 'foo';
window['test'] = 'value mutated';
console.log(test);
// value emitted 'value mutated'

В приведенном выше примере кода значение, которое будет утешаться, будет value mutated.Это связано с тем, что в любой настройке браузера объект window + document будет кэшировать все переменные.Это позволяет изменять значения, поскольку компилятор не будет регистрироваться как изменяемое значение только для чтения.Мы создаем указатель (так сказать) на значение, используя окно, которое создает другую опорную точку.Так что да, const является изменяемым для значений, отличных от строк или чисел, даже если это значение только для чтения!

Пример кода - (попытка) для изменения Enum

Попыткаизменить неизменяемое перечисление в Typescript

enum testTwo {
  test = 'value immutable'
}
const pointerToTestTwo = 'testTwo.test';

window[testTwo.test] = 'value mutated';
console.log(testTwo.test);
// value emitted 'value immutable'

не будет.Это потому, что перечисление в машинописи компилируется как IIFE (Немедленно Вызывается функция Expression), без каких-либо опорной точки.Единственный способ изменить enum - создать другую функцию, которая ссылается на enum.

Так что да, чтобы закончить эту точку.Const только для чтения действительно изменчив в Javascript во всех сценариях, в отличие от enum в Typescript, который является неизменным.Не стесняйтесь взглянуть на мою статью, которая обсуждает это немного больше: Enums V. Константы

...