如果使用相同名称的 'let' 两次(在 for 循环中),Babel 会重新声明函数参数
Babel redeclares function parameter if 'let' with the same name is used twice (in a for loop)
当我做这样(愚蠢的)事情时:
function doBar(bar) {
for (let bar = 0; bar < 10; bar++) {
let bar = true;
}
}
Babel 生成这个:
function doBar(bar) {
for (var bar = 0; bar < 10; bar++) {
var _bar = true;
}
// bar is redeclared and has the value 10
}
我使用了带有 es2015
选项的 babeljs.io 工具。
问题:它应该那样工作吗?
为什么生成的javascript不是这样的:
for (var _bar = 0; _bar < 10; _bar++) {
var _bar = true;
}
或
for (var _bar = 0; _bar < 10; _bar++) {
var _bar2 = true;
}
编辑: 向 babeljs.io example 添加了一些控制台输出以显示如何重新声明函数 variabel。
let
和var
不一样。
let
在块范围内定义一个变量,例如您的 for 循环。
var
在全局或函数范围内定义一个变量。
因此,当您获得代码时:
function doBar(bar) {
for (let bar = 0; bar < 10; bar++) {
let bar = true;
}
}
外部 "bar" 是为函数 doBar
定义的,而内部 "bar" 是为 for(){}
块范围定义的。
没有"redeclaring"。当 bable 转换它时,你会得到预期的行为,外部 "bar" 在函数内,当你退出 for 循环时它保持在最大值,内部 _bar
是一个完全不同的变量。
因为它们都被转换为 var
而不是 let
并且被提升了。
评论相关例子:
如果你有这种类型的代码:
function doBar(bar) {
for (let bar = 0; bar < 10; bar++) {
let bar = true;
}
}
首先,这在语义上是错误的。这包含重新声明。这两个 bar
变量都在 for 块的范围内声明。但是你不会抛出任何错误,没有 babel 也是如此。由于变量 bar 的重新声明发生在 for 的范围块内,for 的 "parameter" bar 被覆盖并且块本身无法访问,但是似乎循环仍然正常 运行s,正确的次数。
因为这个 "silent error" 和块中重新声明的变量 let bar
,babel 不认为这两个变量是相同的,它们是不同的。 错误的原因 在于通过在块内重新声明变量,您有效地使块自己的变量无法访问任何东西,无论是块还是块外.
现在从 babel 的角度来看,循环应该 运行,循环的参数在 for 括号内外的任何地方都不可访问,因此这是一个孤立的 "scope" for bar
在 for.
中
与 let
不同,var
可以在不引发错误的情况下重新声明,但是这种静默重新声明在两种情况下都不会引发错误,其中一个应该已经上升并且这就是导致问题的原因。
解决方案是编写正确的代码,但你是 100% 正确的,这不是正确的行为,但是,非 bable 代码的常规 javascript 解释器也不是,因为它应该抛出一个错误,你不能 expect/blame babel 以错误的方式解释错误的代码。
Babel 只是部分正确。
When I do something (stupid) like this:
function doBar(bar) {
for (let bar = 0; bar < 10; bar++) {
let bar = true;
}
}
doBar("BAR");
…那么你可能没想到这里有 三个不同的变量 命名为 bar
在三个不同的范围内。
但这是真的:
- 参数声明的function-scope(
var
-like)bar
- 在
foo
header中的let
声明引入的loop-scopedbar
,其special scoping rules
- block-scoped
bar
由let
声明在形成循环的块中引入body语句
它们都有独立的值(1:字符串,2:整数,3:布尔值)并且互不影响。这一点很明显,因为没有语法错误被抛出 - 否则任何 let
重新定义一个 function-scoped 变量(参数,var
声明)或一个 let
在与其自身相同的范围内会抛出早期错误。
Babel generates this […]. Should it work that way?
没有。正如你在doFoo
中所看到的,Babel实际上认识到变量1和2是不同的。它还确实认识到 2 和 3 是不同的。但是一旦你引入所有三个,它就会混淆 1 和 2,将它们转换为相同的标识符。
当我做这样(愚蠢的)事情时:
function doBar(bar) {
for (let bar = 0; bar < 10; bar++) {
let bar = true;
}
}
Babel 生成这个:
function doBar(bar) {
for (var bar = 0; bar < 10; bar++) {
var _bar = true;
}
// bar is redeclared and has the value 10
}
我使用了带有 es2015
选项的 babeljs.io 工具。
问题:它应该那样工作吗?
为什么生成的javascript不是这样的:
for (var _bar = 0; _bar < 10; _bar++) {
var _bar = true;
}
或
for (var _bar = 0; _bar < 10; _bar++) {
var _bar2 = true;
}
编辑: 向 babeljs.io example 添加了一些控制台输出以显示如何重新声明函数 variabel。
let
和var
不一样。
let
在块范围内定义一个变量,例如您的 for 循环。
var
在全局或函数范围内定义一个变量。
因此,当您获得代码时:
function doBar(bar) {
for (let bar = 0; bar < 10; bar++) {
let bar = true;
}
}
外部 "bar" 是为函数 doBar
定义的,而内部 "bar" 是为 for(){}
块范围定义的。
没有"redeclaring"。当 bable 转换它时,你会得到预期的行为,外部 "bar" 在函数内,当你退出 for 循环时它保持在最大值,内部 _bar
是一个完全不同的变量。
因为它们都被转换为 var
而不是 let
并且被提升了。
评论相关例子:
如果你有这种类型的代码:
function doBar(bar) {
for (let bar = 0; bar < 10; bar++) {
let bar = true;
}
}
首先,这在语义上是错误的。这包含重新声明。这两个 bar
变量都在 for 块的范围内声明。但是你不会抛出任何错误,没有 babel 也是如此。由于变量 bar 的重新声明发生在 for 的范围块内,for 的 "parameter" bar 被覆盖并且块本身无法访问,但是似乎循环仍然正常 运行s,正确的次数。
因为这个 "silent error" 和块中重新声明的变量 let bar
,babel 不认为这两个变量是相同的,它们是不同的。 错误的原因 在于通过在块内重新声明变量,您有效地使块自己的变量无法访问任何东西,无论是块还是块外.
现在从 babel 的角度来看,循环应该 运行,循环的参数在 for 括号内外的任何地方都不可访问,因此这是一个孤立的 "scope" for bar
在 for.
与 let
不同,var
可以在不引发错误的情况下重新声明,但是这种静默重新声明在两种情况下都不会引发错误,其中一个应该已经上升并且这就是导致问题的原因。
解决方案是编写正确的代码,但你是 100% 正确的,这不是正确的行为,但是,非 bable 代码的常规 javascript 解释器也不是,因为它应该抛出一个错误,你不能 expect/blame babel 以错误的方式解释错误的代码。
Babel 只是部分正确。
When I do something (stupid) like this:
function doBar(bar) { for (let bar = 0; bar < 10; bar++) { let bar = true; } } doBar("BAR");
…那么你可能没想到这里有 三个不同的变量 命名为 bar
在三个不同的范围内。
但这是真的:
- 参数声明的function-scope(
var
-like)bar
- 在
foo
header中的let
声明引入的loop-scopedbar
,其special scoping rules - block-scoped
bar
由let
声明在形成循环的块中引入body语句
它们都有独立的值(1:字符串,2:整数,3:布尔值)并且互不影响。这一点很明显,因为没有语法错误被抛出 - 否则任何 let
重新定义一个 function-scoped 变量(参数,var
声明)或一个 let
在与其自身相同的范围内会抛出早期错误。
Babel generates this […]. Should it work that way?
没有。正如你在doFoo
中所看到的,Babel实际上认识到变量1和2是不同的。它还确实认识到 2 和 3 是不同的。但是一旦你引入所有三个,它就会混淆 1 和 2,将它们转换为相同的标识符。