为什么链接到 Promise.resolve() 的 .then() 允许重新分配 const 声明?

2024-02-06

假设一个变量声明为const无法重新分配或删除,请参阅

  • JavaScript 中有常量吗? https://stackoverflow.com/questions/130396/are-there-constants-in-javascript/

  • JavaScript const 关键字 https://stackoverflow.com/questions/20014513/javascript-const-keyword

  • 是否可以删除使用 const 声明的变量? https://stackoverflow.com/questions/42424019/is-it-possible-to-delete-a-variable-declared-using-const?

为什么可以将值重新分配给声明的变量const在传递给的函数内.then()链接到Promise.resolve() where 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声明,以及当该程序不可能时。本质上,尝试创建一个标识符,该标识符在尝试为标识符分配不同值的任何范围内抛出错误 - 无论是函数范围、块范围还是代码中的任何位置 - 一个“superconst“ 标识符,或当前可能最接近该描述的标识符,具体取决于引擎。是Map or WeakMap or class我们目前最新的浏览器实现中最接近的是什么?


您没有分配给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 无法阻止使用本地作用域中新声明的同名变量覆盖更高作用域的变量。这不是语言功能。当解释器解析变量名时,它会从本地到全局搜索范围层次结构,因此首先找到(并使用)本地定义。更高范围的定义在该范围内被“覆盖”或“隐藏”。这就是他们设计变量名称解析以在该语言中工作的方式。

这样做也有很多好处,因为有人突然声明您没有使用或什至不知道的较高作用域变量永远不会意外破坏您的较低作用域声明。当您自己声明冲突并且实际上想要使用更高范围的命名时,这只是一个编码错误。如果您打算使用同名的更高范围的变量,则不必声明冲突的名称。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么链接到 Promise.resolve() 的 .then() 允许重新分配 const 声明? 的相关文章

随机推荐