为什么在一个函数内部使用let声明的某些变量在另一个函数中变得可用,而另一些变量导致引用错误?

2020/10/29 21:03 · javascript ·  · 0评论

我不明白为什么在函数内部声明变量时会表现得如此奇怪。

  1. first函数中,我使用let变量bc10进行声明

    b = c = 10;
    

    second函数中,我显示:

    b + ", " + c
    

    这表明:

    10, 10
    
  2. 同样在first函数中,我声明a10

    let a = b = c = 10;
    

    但是在second函数中它显示了一个错误:

    找不到变量: a

  3. 现在在first函数中,我声明d20

    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()无需使用即可动态创建变量bcvarlet

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

在使事情变得奇怪之前,让我们先了解一些基本知识:

varlet都用于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关键字的变量应仅在块范围内可用,而在外部函数中不可用...

您以这种方式声明的每个变量都没有使用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();

这是因为当您不使用时,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个有趣的方面:

  1. var 将变量的范围限制为在其定义的块中。 “ var”用于本地范围。)

  2. let允许在块内临时覆盖外部变量的值。

  3. 简单地声明一个不带varlet的变量,将使该变量成为全局变量,而不管它在何处声明。

这是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

说明:

变量ab被放入' first() '内部,而没有var或let关键字。

因此,ab是全局的,因此可以在整个程序中访问。

在名为“ second”的函数中,语句“ let a = 5”仅在函数范围内将a的值临时设置为“ 5 ”。

在“ second()范围之外,即IE,在全局范围内,“ a的值将如先前所定义。

本文地址:http://javascript.askforanswer.com/weishenmezaiyigehanshuneibushiyongletshengmingdemouxiebianliangzailingyigehanshuzhongbiandekeyongera.html
文章标签: ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!