检查下面的代码。计数器声明为const。当你运行它时,它不应该允许它在任何情况下改变!
function increment(counter) {
counter += 1;
}
function test() {
const counter = 1;
increment(counter);
}
转换后,会生成以下代码。这允许const计数器递增!
function increment(counter) {
counter += 1; // Counter is declared const, still it can be changed!
}
function test() {
var counter = 1;
increment(counter);
}
我只是想了解,无论是Babel转换还是JavaScript规范都存在问题。
修改
我知道,与ES6不同,当前版本的JS不支持const
。我担心的是,如果我使用已编译的JavaScript,我可能会遇到未知的const相关错误。那可以吗?
答案 0 :(得分:8)
计数器被声明为const,仍然可以更改!
在转换后的代码中有两个名称为counter
的标识符:
counter
内的参数 increment
。counter
内的变量 test
。他们是完全独立的!
参数从不"常量",始终可以为它们分配新值。它对传递给函数的内容没有影响,因为所有参数都是通过值传递,即increment
传递变量的值 counter
,然后将其分配到参数 counter
。
我们可以通过在函数调用之前和之后记录变量的值来轻松验证这一点:
function increment(counter) {
counter += 1;
}
function test() {
var counter = 1;
console.log('value before', counter);
increment(counter);
console.log('value after', counter);
}
test();

我只想了解Babel转换或JavaScript规范是否存在问题
两者都没有。无论您是使用var
还是const
来声明counter
,它都能完全指定。
我担心的是,如果我使用已编译的JavaScript,我可能会遇到与const相关的未知错误。
不,那不是这样的。是什么让const
特别?您无法为其分配新值并且它被阻止作用域。因此,让我们来看看Babel在违反这两个限制时所做的事情:
输入:
const foo = 21;
foo = 42;
Babel输出:
Babel拒绝使用错误
来转换代码SyntaxError: intput.js: "foo" is read-only
1 | const foo = 42;
> 2 | foo = 21;
| ^
3 |
输入:
{
const foo = 21;
}
console.log(foo); // trying to access const outside of block
Babel输出:
"use strict";
{
var _foo = 21;
}
console.log(foo); // trying to access const outside of block
Babel重命名了块范围的变量。 foo
不存在(如预期的那样)。
答案 1 :(得分:0)
这里有两件事:
value
而不是变量本身(正如其他答案所解释的那样)const
转换为var
并仍然保持不可重新分配合同的方式。我将在答案中解释这一部分:关于babel和const的事情是,它只能通过静态分析工作
工作代码的转换会将const
转换为var
,因为ES5中存在所有内容。
const a = 0
const b = a + 1;
// becomes
var a = 0;
var b = a + 1;
当babel发现你为你的变量分配不同的值时会发生魔力:
const a = 1;
a = a + 1;
// becomes
function _readOnlyError(name) { throw new Error("\"" + name + "\" is read-only"); }
var a = 1;
a = (_readOnlyError("a"), a + 1);
因为babel可以告诉它会通过读取代码引发错误,它会替换错误发生时的错误点。
因此,99%的情况下,const会在转换为ES5时阻止重新分配。
您的代码未被转换为抛出错误的原因是因为第1部分。