Почему.then(), связанный с Promise.resolve(), позволяет переназначить объявление const?

Учитывая, что переменная объявлена ​​с const не может быть переназначен или удален см.

почему возможно переназначить значение переменной, объявленной с const в функции, переданной .then() прикован к Promise.resolve() где const переменная передается, но невозможно переназначить const переменная с функцией, переданной в .then() прикован к Promise конструктор где const переменная передается resolve() параметр Promise конструктор resolver функционировать?

"use strict"
const state = "123";
Promise.resolve(state)
.then(state => {
  console.log(state); // `"123"`
  state = 456; // reassign `const` variable `state` to `"456"`
  return state
})
.then(state => console.log(state)) // `"456"`
// not reached
.catch(err => console.error(err.message));

{
  "use strict";
  const state = "123";
  new Promise(resolve => {
    console.log(state); // `"123"`
    state = "456"; // reassign `const` variable `state` to `456`
    resolve(state);
  })
  .then(state => {
    console.log(state);
  })
  // `Error: Assignment to constant variable.`
  .catch(err => console.error(err.message)); 
}


Изменить, Обновлено

Чтобы прояснить основу и мотивацию для запроса, Вопрос представляет собой попытку определить, когда можно использовать идентификатор, который совпадает с const декларации, и когда эта процедура невозможна. По сути, попытка создать идентификатор, который выдает ошибку в любой области видимости, когда делается попытка присвоить идентификатору другое значение - будь то область действия функции, область блока или где-либо в коде - a " superconst "неопределитель" или наиболее близкий к этому описанию в настоящее время возможный, в зависимости от двигателя. Map или же WeakMap или же class самый близкий у нас в настоящее время в новейших реализациях браузера?

2 ответа

Решение

Вы не назначаете на const переменная. Вместо этого вы присваиваете параметру функции, который вы дали то же имя. Этот параметр функции является неконстантной копией переменной, поэтому вы можете назначить ее.

Я постараюсь собрать все свои комментарии в более подробный ответ.

В коде здесь:

"use strict"
const state = "123";
Promise.resolve(state).then(state => {
  console.log(state); // `"123"`
  state = 456; // reassign `const` variable `state` to `"456"`
  return state
}).then(state => console.log(state)) // `"456"`
  // not reached
.catch(err => console.error(err.message));

Во-первых, вы определяете const state = "123" переменная. Любая попытка изменить содержание этого точного state переменная выдаст исключение.

Затем, когда вы делаете это:

Promise.resolve(state).then(state => {

Это объявляет .then() функция-обработчик, которая принимает один аргумент и имя этого аргумента state, Когда .then() вызывается обработчик, все, что передается в качестве этого одного аргумента .then() обработчик копируется в эту новую переменную аргумента с именем state, Аргументы функции не являются const, Они могут быть назначены на.

Поскольку теперь вы создали ДВЕ отдельные переменные с одним и тем же именем, и одна находится в более широкой области видимости, когда вы находитесь внутри .then() обработчик, этот аргумент функции с именем state "переопределяет" или "скрывает" другую переменную с тем же именем. Когда вы пытаетесь получить доступ state внутри .then() handler, единственная переменная, к которой вы можете обращаться, используя это имя, является параметром функции. Этот параметр функции является копией другой переменной состояния в силу того, что он передается .then() обработчик в качестве аргумента. Все аргументы функции являются копиями. Javascript не имеет истинных типов ссылочных переменных.

Кроме того, аргументы функции не являются const так что вы можете назначить им.

Итак, когда вы state = "456"; внутри этого .then() обработчик, вы просто присваиваете аргумент функции. Поскольку вы создали конфликт имен, на самом деле нет способа получить доступ к const state переменная. Интерпретатор JS находит определение, наиболее близкое по объему к тому месту, где вы пытаетесь получить к нему доступ.


Я думаю, что ваша путаница прояснится, если вы просто прекратите создавать конфликтующее имя переменной. Если вы делаете это так (назовите параметр localState):

"use strict"
const state = "123";
Promise.resolve(state).then(localState => {
  console.log(state); // `"123"`
  state = 456; // reassign `const` variable `state` to `"456"`
  return state
}).then(state => console.log(state)) // `"456"`
  // not reached
.catch(err => console.error(err.message));

Затем вы увидите исключение при попытке назначить state потому что вы не создали конфликтующую локальную переменную с тем же именем, поэтому ваша попытка назначить state = 456 действительно будет пытаться назначить на const переменная и интерпретатор будет возражать.


Насколько я знаю, Javascript не может предотвратить переопределение переменной с более высокой областью действия с помощью недавно объявленной переменной с тем же именем в локальной области видимости. Это просто не языковая особенность. Когда интерпретатор разрешает имя переменной, он ищет иерархию области действия от локальной до глобальной, поэтому сначала определяются (и используются) локальные определения. Определения с более высокой областью охвата "переопределяются" или "скрываются" в этой области. Именно так они разработали разрешение имен переменных для работы на языке.

В этом тоже есть много преимуществ: кто-то, внезапно объявивший переменную с более высокой областью действия, которую вы не используете или даже не подозреваете, никогда не будет случайно нарушать ваши объявления с более низкой областью действия. Когда вы сами объявляете конфликт и хотите использовать имя с более высокой областью действия, это просто ошибка кодирования. Вы не должны объявлять конфликтующее имя, если собираетесь использовать переменную с более высокой областью действия с тем же именем.

Здесь константа state переменная не меняется. Вы изменяете значение параметра, которое передается в функцию разрешения. Вы можете проверить это, просто выполнив console.log(state) ведь ваш код и вывод будут 123,

Другие вопросы по тегам