为什么.then()链接到Promise.resolve()允许重新分配const声明? [英] Why does .then() chained to Promise.resolve() allow const declaration to be reassigned?

查看:156
本文介绍了为什么.then()链接到Promise.resolve()允许重新分配const声明?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于用 const 声明的变量无法重新分配或删除,请参阅





为什么可以将值重新分配给传递给 .then()的函数中用 const 声明的变量链接到 Promise。 resolve()其中传递 const 变量,但无法重新分配 const 变量,函数传递给 .then()链接到 Promise 构造函数,其中 const 变量传递给 resolve()参数 Promise constructor 解析器功能?



  use strictconst state =123; Promise.resolve(state).then(state => {console.log(state); //123`state = 456; //将`const`变量`state`重新分配给`456`return state})。then(state => console.log(state))//`456`// not reach.catch(err = > console.error(err.message));  



  {use strict; const state =123; new Promise(resolve => {console.log(state); //`123`state =456; //将`const`变量`state`重新分配给`456` resolve(state);})。然后(state => {console.log(state);})//`错误:赋值给常量变量.catch(err => console.error(err.message)); }  






编辑,更新



为澄清查询的依据和动机,该问题试图确定何时可以使用与<$ c $相同的标识符。 c> const 声明,以及何时无法执行该过程。实质上,尝试创建一个标识符,在任何范围内抛出错误,尝试为标识符分配不同的值 - 无论是函数范围,块范围还是代码中的任何位置 - superconst istifier,或最接近当前可能的描述,具体取决于引擎。 地图 WeakMap 我们目前最接近的地方在最新的浏览器实现?

解决方案

您没有分配给 const 变量。而是分配给您赋予相同名称的函数参数。该函数参数是变量的非常量副本,因此您可以分配给它。



我将尝试将所有注释收集到更完整解释的答案中。



在这里的代码中:

 use strict
const state =123;
Promise.resolve(state).then(state => {
console.log(state); //`123`
state = 456; //重新分配`const`变量`state`到`456`
返回状态
})。then(state => console.log(state))//`456`
// not达到
.catch(err => console.error(err.message));

首先,您定义 const state =123变量。任何改变那个确切 state 变量内容的尝试都会抛出异常。



然后,当你这样做时:

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

声明一个 .then()处理函数,该函数接受一个参数和该参数的名称是 state 。当调用 .then()处理程序时,将任何一个参数传递给 .then()处理程序被复制到名为 state 的新参数变量中。函数参数不是 const 。可以将它们分配给。



因为你现在已经创建了两个具有相同名称的独立变量,并且一个变量具有更高的范围,当你在 .then()处理程序中时,该函数参数名为 state 覆盖或隐藏其他同名变量。当您尝试在 .then()中访问 state handler,使用该名称时可以访问的唯一变量是函数参数。该函数参数是另一个状态变量的副本,因为它作为参数传递给 .then()处理程序。所有函数参数都是副本。 Javascript没有真正的引用变量类型。



此外函数参数不是 const 所以你可以分配它们。 / p>

所以,当你 state =456; 里面的那个 .then() handler,你只是分配给函数参数。因为您已经创建了命名冲突,所以实际上无法访问更高范围的 const状态变量。 JS解释器找到的范围最接近您尝试访问它的范围。






我认为你的困惑如果您只是停止创建冲突的变量名称,将被清除。如果你这样做(命名参数 localState ):

  use strict
const state =123;
Promise.resolve(state).then(localState => {
console.log(state); //`123`
state = 456; //重新分配`const`变量`state`到`456`
返回状态
})。then(state => console.log(state))//`456`
// not达到
.catch(err => console.error(err.message));

然后,当您尝试分配到州时,您将看到异常因为您没有创建具有相同名称的冲突局部变量,所以您尝试分配 state = 456 确实会尝试分配给 const 变量,解释器将对象。






据我所知, Javascript无法阻止使用本地范围内新声明的同名变量覆盖更高范围的变量。这不是语言功能。当解释器解析变量名时,它会将范围层次结构从本地搜索到全局,以便首先找到(并使用)本地定义。更高范围的定义在该范围内覆盖或隐藏。这就是他们如何设计变量名称解析以使用该语言。



这也有很多好处,因为有人突然宣布你没有使用或甚至不知道的更高范围的变量将永远不会意外地打破你的低级范围声明。当你自己声明冲突并且你真的想要使用更高范围的命名时,那只是一个编码错误。如果您打算使用同名的更高范围的变量,则必须不声明冲突的名称。


Given that a variable declared with const cannot be reassigned or deleted see

why is it possible to reassign a value to a variable declared with const within a function passed to .then() chained to Promise.resolve() where const variable is passed, but it is not possible to reassign the const variable with function passed to .then() chained to Promise constructor where const variable is passed to resolve() parameter of Promise constructor resolver function?

"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)); 
}


Edit, Updated

To clarify the basis and motivation for the inquiry, the Question is an attempt to determine when an identifier can be used which is the same as a const declaration, and when that procedure is not possible. In essence, trying to create an identifier which throws an error in any scope where an attempt is made to assign the identifier a different value - whether function scope, block scope or anywhere in the code - a "superconst" indetifier, or the closest to that description currently possible, depending on the engine. Are Map or WeakMap or class the closest we currently have at newest browser implementations?

解决方案

You are not assigning to the const variable. You are instead assigning to the function parameter that you gave the same name. That function parameter is a non-const copy of the variable so you are allowed to assign to it.

I will try to collect all my comments into a more fully explained answer.

In code here:

"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));

First, you define your const state = "123" variable. Any attempt to change the contents of that exact state variable will throw an exception.

Then, when you do this:

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

That declares a .then() handler function that takes one argument and the name of that argument is state. When the .then() handler is called, whatever is passed as that one argument to the .then() handler is copied into this new argument variable named state. Function arguments are not const. They can be assigned to.

Because you've now created TWO separate variables with the same name and one is at a higher scope, when you are inside the .then() handler, that function argument named state "overrides" or "hides" the other variable of the same name. When you attempt to access state inside the .then() handler, the ONLY variable you can access when using that name is the function parameter. That function parameter is a copy of the other state variable by virtue of being passed to the .then() handler as an argument. All function arguments are copies. Javascript has no true reference variable types.

Furthermore function arguments are not const so you can assign to them.

So, when you state = "456"; inside that .then() handler, you are just assigning to the function argument. Because you've created a naming conflict, there is actually no way to access the higher scoped const state variable. The JS interpreter finds the definition that is closest in scope to where you are attempting to access it.


I think your confusion will be cleared up if you just stop creating a conflicting variable name. If you do it like this (name the parameter 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));

Then, you will see an exception when you attempt to assign to state because you have not created a conflicting local variable with that same name so your attempt to assign state = 456 will indeed be attempting to assign to a const variable and the interpreter will object.


As best I know, Javascript has no way to prevent overriding a higher scoped variable with a newly declared variable of the same name in the local scope. That just isn't a language feature. When the interpreter resolves a variable name, it searches the scope hierarchy from local to global so local definitions are found (and used) first. Higher scoped definitions are "overriden" or "hidden" within that scope. That's just how they designed variable name resolution to work in the language.

There are many benefits to this too in that somebody suddenly declaring a higher scoped variable that you aren't using or aren't even aware of will never accidentally break your lower scoped declarations. When you yourself declaring a conflict and you actually want to use the higher scoped named, that's just a coding mistake. You have to not declare a conflicting name if you intend to use the higher scoped variable of the same name.

这篇关于为什么.then()链接到Promise.resolve()允许重新分配const声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆