为什么函数内部的变量如此奇怪?

问题描述 投票:46回答:4

我不明白为什么在函数内部声明变量时,行为为何如此奇怪。示例:

function first() {
   let a = b = c = 10;
   var d = 20;
   second();
}

function second() {
   alert(b + ", " + c); //shows "10, 10"
   alert(a); //reference error
   alert(d); //reference error
}
javascript variable-declaration
4个回答
57
投票

这是因为您实际上是在说:

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”。


33
投票

在功能first()中,无需使用bc即可即时创建变量varlet

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()

中可用的原因

来自documentation

在执行分配时,将值分配给未声明的变量会隐式将其创建为全局变量(它成为全局对象的属性)。

为避免这种情况,您可以使用"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();

9
投票

在称奇事物之前先让我们了解一些基础知识:

varlet都用于javascript中的变量声明例如

var one = 1;
let two = 2;

也可以在不使用var或let的情况下声明变量例如

three = 3;

现在上述方法之间的区别在于:

var是函数范围的

让块作用域。

while

不使用var / let关键字声明的变量的范围将成为global,而不管声明在哪里。可以从网页的任何位置访问全局变量。(不建议使用,因为可能会意外修改全局变量。)

现在根据这些概念,让我们看一下所讨论的代码:

 function first() {
   let a = b = c = 10; 
   /* 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
}

2
投票

使用let关键字的变量应仅在块范围内可用,而在外部函数中不可用...

您以这种方式声明的每个变量都没有使用letvar。您在变量声明中缺少逗号。

建议不推荐声明不带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();
© www.soinside.com 2019 - 2024. All rights reserved.