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

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

问题描述

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

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

JavaScript const 关键字

是否可以删除一个使用 const 声明的变量??

为什么可以在传递给 .then() 链接到 Promise.resolve() 的函数中将值重新分配给使用 const 声明的变量 其中 const 变量被传递,但不可能重新分配 const 变量与传递给 .then() 链接的函数到 Promise 构造函数,其中 const 变量被传递给 Promise 构造函数 resolverresolve() 参数代码>函数?

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

编辑,更新

为了澄清调查的基础和动机,该问题试图确定何时可以使用与 const 声明相同的标识符,以及何时无法使用该程序.本质上,尝试创建一个标识符,该标识符会在尝试为标识符分配不同值的任何范围内引发错误——无论是函数范围、块范围还是代码中的任何位置——superconst" 标识符,或与当前可能的描述最接近的标识符,具体取决于引擎.MapWeakMapclass 是我们目前在最新浏览器实现中最接近的吗?

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?

推荐答案

您没有分配给 const 变量.相反,您正在分配给您提供相同名称的函数参数.该函数参数是变量的非常量副本,因此您可以分配给它.

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.

这里的代码:

"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 变量内容的尝试都会引发异常.

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

然后,当你这样做时:

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

这声明了一个 .then() 处理函数,它接受一个参数并且该参数的名称是 state.当调用 .then() 处理程序时,任何作为该参数传递给 .then() 处理程序的内容都会复制到名为 state 的新参数变量中.函数参数不是 const.他们可以被分配到.

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.

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

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.

此外,函数参数不是 const,因此您可以分配给它们.

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

因此,当您在该 .then() 处理程序中 state = "456"; 时,您只是分配给函数参数.因为您已经创建了命名冲突,所以实际上无法访问更高范围的 const state 变量.JS 解释器会找到在范围内最接近您尝试访问它的定义.

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.

我认为,如果您停止创建有冲突的变量名,您的困惑就会迎刃而解.如果你这样做(命名参数localState):

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

然后,当您尝试分配给 state 时,您将看到一个异常,因为您尚未创建具有相同名称的冲突局部变量,因此您尝试分配 state = 456 确实会尝试分配给 const 变量,解释器会反对.

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.

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

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.

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

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