我不明白为什么变量在函数内部声明时会表现得如此奇怪。
>
在first
函数中,我使用let
声明值为10的变量b
和c
:
b = c = 10;
在second
函数中显示:
b + ", " + c
这表明:
10, 10
同样在first
函数中,我声明了值为10的A
:
let a = b = c = 10;
但在second
函数中显示错误:
找不到变量:A
现在,在first
函数中,我声明值为20的d
:
var d = 20;
但在second
函数中,它显示了与前面相同的错误,但使用了变量d
:
找不到变量:D
示例:
null
function first() {
let a = b = c = 10;
var d = 20;
second();
}
function second() {
console.log(b + ", " + c); //shows "10, 10"
try{ console.log(a); } // Rreference error
catch(e){ console.error(e.message) }
try{ console.log(d); } // Reference error
catch(e){ console.error(e.message) }
}
first()
null
因为你实际上是在说:
c = 10;
b = c;
let a = b;
而不是你认为你在说什么,那就是:
let a = 10;
let b = 10;
let c = 10;
您会注意到,无论向链中添加多少变量,都只有第一个变量(a)会导致错误。
这是因为“let”将变量的范围限定在声明它的块(或者,“local”,或多或少的意思是“在括号中”)。
如果您声明了一个不带“let”的变量,那么它将全局地影响该变量的作用域。
所以,在你设置变量的函数中,所有的东西都得到值10(如果你放一个断点,你可以在调试器中看到这一点)。如果在第一个函数中放入a、b、c控制台日志,那么一切都很好。
但是当您离开该函数时,第一个(a)--记住,从技术上讲,按照赋值顺序,它是最后一个--“消失”了(同样,如果您在第二个函数中设置了断点,您可以在调试器中看到这一点),但是其他两个(或者您添加了多少个)仍然可用。
这是因为,“let”仅适用于(因此仅适用于局部范围)链中的第一个变量--也是技术上最后一个被声明和赋值的变量。其余的技术上没有“让”在他们的前面。所以它们在技术上是全局声明的(即在全局对象上),这就是它们出现在第二个函数中的原因。
试试吧:去掉“让”关键字。你所有的变量现在都可用了。
“var”具有类似的局部作用域效果,但在变量如何“提升”方面有所不同,这是您应该明确理解的,但与您的问题没有直接关系。
(顺便说一句,这个问题会有足够多的专业JS开发人员让它成为一个好的问题)。
强烈建议您花点时间研究一下在JS中如何声明变量的差异:不使用关键字、使用“let”和使用“var”。
在函数first()
中,变量b
和c
是动态创建的,而不使用var
或let
。
let a = b = c = 10; // b and c are created on the fly
不同于
let a = 10, b = 10, c = 10; // b and c are created using let (note the ,)
它们变成了隐含的全局。这就是它们在second()
中可用的原因
来自文档
为未声明的变量赋值,在执行赋值时隐式地将其创建为全局变量(它成为全局对象的属性)。
为了避免这种情况,可以使用“use strict”
在使用未声明的变量时提供错误
null
"use strict"; // <-------------- check this
function first() {
/*
* With "use strict" c is not defined.
* (Neither is b, but since the line will be executed from right to left,
* the variable c will cause the error and the script will stop)
* Without, b and c become globals, and then are accessible in other functions
*/
let a = b = c = 10;
var d = 20;
second();
}
function second() {
console.log(b + ", " + c); //reference error
console.log(a); //reference error
console.log(d); //reference error
}
first();