我错误地在一个函数中写了一个参数的重新声明为const
而不是抛出SyntaxError: Identifier 'bar' has already been declared
我最终得到了ReferenceError: bar is not defined.
。
导致这种行为的原因是什么?这不是预期的错误,让我困惑了几分钟。
示例代码:
function foo(bar) {
try {
console.log(bar);
const bar = 123;
} catch(err) { console.log(err) }
}
foo(456);
如果我不在try / catch中包装声明,我会得到(我认为是)预期的错误。
答案 0 :(得分:18)
常量是块范围的,非常类似于使用let语句定义的变量。
由于您将bar
包装在大括号块内,因此其定义与该块相关。并且因为在该块内部有另一个bar
声明,尽管在调用它之后,编译器将尝试使用这个新定义的bar
而不是传入的参数。将它们重命名为单独的参数以减轻混淆,因为可以假设它们因为您的声明而持有不同的数据。
答案 1 :(得分:8)
因为const
声明是块作用域的,所以const bar
声明会被提升到块的开头。 (在try {
之后)
这意味着当您尝试登录时,bar
实际上并未定义,因为提升会覆盖/隐藏参数{{1 }}
答案 2 :(得分:8)
const
和let
根本没有被提升是一个神话。他们一半 -hoisted。 :-)即:在一个区块内,如果该区块中的任何位置出现const bar
或let bar
(或class bar { }
),则bar
之前无法使用function foo(bar) {
// `bar` is fine here
try {
// Temporal Dead Zone, `bar` cannot be used here
console.log(bar);
// End of TDZ
const bar = 123;
// `bar` would be fine here
} catch(err) { console.log(err) }
}
foo(456);
块中的声明 - 即使它存在于包含范围内。块的开头和声明之间的区域称为 Temporal Dead Zone :
<?= $this->Form->create('Posts', array('url' => array('controller' => 'MyController', 'action' => 'index')));?>
<?= $this->Form->input('title', array('type'=>'title','class'=>'form-control mr-sm-2'));?>
<?= $this->Form->textarea('text', array('type'=>'text','rows' => '3','class'=>'form-control'));?>
<?= $this->Form->submit('Posten', array('class'=>'btn btn-outline-success my-2 my-sm-0','style'=>'float:right'));?>
<?= $this->Form->end();?>
答案 3 :(得分:3)
从这里采取https://tylermcginnis.com/videos/var-let-const/
var是函数作用域,如果你尝试使用声明的变量 在实际声明之前的var,你只是得到了未定义。常量 并且如果您尝试使用const或let,则阻止作用域 在声明之前变量你将得到一个引用错误。