我不明白为什么在函数内部声明变量时会表现得如此奇怪。
-
在
first
函数中,我使用let
变量b
和c
值10进行声明:b = c = 10;
在
second
函数中,我显示:b + ", " + c
这表明:
10, 10
-
同样在
first
函数中,我声明a
为10:let a = b = c = 10;
但是在
second
函数中它显示了一个错误:找不到变量:
a
-
现在在
first
函数中,我声明d
为20:var d = 20;
但是在
second
函数中,它显示出与以前相同的错误,但带有变量d
:找不到变量:
d
例:
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()
这是因为您实际上是在说:
c = 10;
b = c;
let a = b;
而不是您想说的是:
let a = 10;
let b = 10;
let c = 10;
您会注意到,无论将多少个变量添加到链中,它都只会是导致错误的第一个(a)。
这是因为“ let”将变量的作用域限定在声明它的块(或“局部”,或多或少的意思是“在方括号中”)。
如果声明不带“ let”的变量,它将在全局范围内定义变量。
因此,在设置变量的函数中,所有值都为10(如果放置断点,则可以在调试器中看到此值)。如果您在第一个函数中为a,b,c放置一个控制台日志,一切都很好。
但是,一旦您离开该功能,第一个(a)-再一次,要记住,从技术上讲,按照分配的顺序,它就是最后一个-“消失”(同样,您可以在调试器(如果您在第二个函数中设置了断点),但其他两个(或添加的数目)仍然可用。
这是因为,“ let”仅适用于(因此仅在本地范围内)链中的第一个变量-再次,从技术上讲,它是最后一个要声明并分配值的变量。从技术上讲,其余的都没有在前面。因此,它们在技术上是全局声明的(即在全局对象上),这就是它们出现在第二个函数中的原因。
尝试一下:删除“ let”关键字。您所有的var现在都可用。
“ 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"
,当使用未声明的变量时,它将提供错误
"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();
在使事情变得奇怪之前,让我们先了解一些基本知识:
var和let都用于JavaScript中的变量声明。例如,
var one = 1;
let two = 2;
也可以在不使用var
或的情况下声明变量let
。例如,
three = 3;
现在,上述方法之间的区别在于:
var
功能范围
和
let
是块作用域的。
而不带
var
/let
关键字声明的变量的范围将变为全局变量,而与声明的位置无关。可以从网页的任何位置访问全局变量(不建议使用,因为可能会意外修改全局变量)。
现在根据这些概念,让我们看一下所讨论的代码:
function first() {
let a = b = c = 10;
/* The above line means:
let a=10; // Block scope
b=10; // Global scope
c=10; // Global scope
*/
var d = 20; // Function scope
second();
}
function second() {
alert(b + ", " + c); // Shows "10, 10" //accessible because of global scope
alert(a); // Error not accessible because block scope has ended
alert(d); // Error not accessible because function scope has ended
}
使用let
关键字的变量应仅在块范围内可用,而在外部函数中不可用...
您以这种方式声明的每个变量都没有使用let
或var
。您在变量声明中缺少逗号。
这是不建议来声明一个变量没有var
关键字。它可能会意外覆盖现有的全局变量。不使用var
关键字声明的变量的范围将变为全局变量,而与声明的位置无关。可以从网页中的任何位置访问全局变量。
function first() {
let a = 10;
let b = 10;
let c = 10;
var d = 20;
second();
}
function second() {
console.log(b + ", " + c); //shows "10, 10"
console.log(a); //reference error
console.log(d); //reference error
}
first();
这是因为当您不使用时,let
或者var
变量正在动态声明时,最好像下面这样声明。
let a = 10;
let b = 10;
let c = 10;
奇怪的问题是由JavaScript中的作用域规则引起的
function first() {
let a = b = c = 10; // a is in local scope, b and c are in global scope
var d = 20; // d is in local scope
second(); // will have access to b and c from the global scope
}
假设您要声明3个初始化为相同值(100)的局部变量。您的first()如下所示。在这种情况下,second()将无法访问任何变量,因为它们是first()的局部变量
function first() {
let a = 100; // a is in local scope init to 100
let b = a; // b is in local scope init to a
let c = b // c is in local scope init to b
var d = 20; // d is in local scope
second(); // will not have access a, b, c, or d
}
但是,如果需要全局变量,则first()将如下所示。在这种情况下,第二个将有权访问所有变量,因为它们在全局范围内
function first() {
a = 100; // a is in global scope
b = a; // b is in global scope
c = b // c is in global scope
d = 20; // d is in global scope
second(); // will have access to a, b, c, and d from the global scope
}
局部变量(也可以在声明它们的代码块中访问)。
代码块是任何{},且代码行之间。
- function(){此处的var,let,const可被整个函数访问},
- for(){这里的var可以被外部作用域访问,让const只能在这里访问},
- 等等
全局变量(也可以在全局范围内访问)。
这些变量将附加到全局对象。全局对象是环境相关的。它是浏览器中的窗口对象。
特别说明:您可以在JavaScript中声明变量,而无需使用var,let,const关键字。以这种方式声明的变量将附加到全局对象,因此可以在全局范围内访问。
a = 100 // is valid and is in global scope
进一步阅读一些文章:
https://www.sitepoint.com/demystifying-javascript-variable-scope-hoisting/
https://scotch.io/tutorials/understanding-scope-in-javascript
HTTPS://www.digitalocean .com / community / tutorials / understanding-variables-scope-hoisting-in-javascript
主要区别是作用域规则。var关键字声明的变量的作用域范围是立即函数主体(因此,函数作用域),而let变量的作用域范围是由{}表示的直接封闭块(因此,块作用域)。当你说
c = 10;
b = c;
let a = b;
c和b的寿命与有趣的寿命相同,但只有一个块的寿命,如果您尝试通过引用访问a总是显示错误,但是c和b是全局的,所以它们不是。添加到链中的变量,只会是导致错误的第一个(a)。这是因为“ let”将变量的作用域限定为块(或“局部”,或多或少的意思是“放在方括号中”)如果在声明变量时未声明“ let”,则该变量将在全局范围内作用。因此,在设置变量的函数中,所有值都为10(如果在调试器中输入断点)。如果您在第一个功能中放置了控制台日志,那么一切都很好。但是,一旦离开该功能,第一个(a)便会记住,再次提醒您,
以下是JavaScript中变量声明的3个有趣的方面:
-
var 将变量的范围限制为在其定义的块中。( “ var”用于本地范围。)
-
let允许在块内临时覆盖外部变量的值。
-
简单地声明一个不带var或let的变量,将使该变量成为全局变量,而不管它在何处声明。
这是let的演示,这是该语言的最新功能:
// File name: let_demo.js
function first() {
a = b = 10
console.log("First function: a = " + a)
console.log("First function: a + b = " + (a + b))
}
function second() {
let a = 5
console.log("Second function: a = " + a)
console.log("Second function: a + b = " + (a + b))
}
first()
second()
console.log("Global: a = " + a)
console.log("Global: a + b = " + (a + b))
输出:
$ node let_demo.js
First function: a = 10
First function: a + b = 20
Second function: a = 5
Second function: a + b = 15
Global: a = 10
Global: a + b = 20
说明:
变量a和b被放入' first() '内部,而没有var或let关键字。
因此,a和b是全局的,因此可以在整个程序中访问。
在名为“ second”的函数中,语句“ let a = 5”仅在函数范围内将“ a ”的值临时设置为“ 5 ”。
在“ second() ”范围之外,即IE,在全局范围内,“ a ”的值将如先前所定义。
文章标签:javascript , variable-declaration
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!
评论已关闭!