JavaScript Let


ECMAScript 2015

ES2015 引入了两个重要的 JavaScript 新关键词:letconst

这两个关键字在 JavaScript 中提供了块作用域(Block Scope)变量(和常量)。

在 ES2015 之前,JavaScript 只有两种类型的作用域:全局作用域函数作用域


全局作用域

全局(在函数之外)声明的变量拥有全局作用域

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h1>JavaScript 全局作用域</h1>
  5. <p>可以从任何脚本或函数中访问全局变量。</p>
  6. <p id="demo">
  7. <script>
  8. var carName = "保时捷";
  9. myFunction();
  10. function myFunction() {
  11. document.getElementById("demo").innerHTML =
  12. "I can display " + carName;
  13. }
  14. </script>
  15. </body>
  16. </html>

全局变量可以在 JavaScript 程序中的任何位置访问。


函数作用域

局部(函数内)声明的变量拥有函数作用域

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h1>JavaScript 局部作用域</h1>
  5. <p>myFunction() 之外的 carName 未定义。</p>
  6. <p id="demo1">
  7. <p id="demo2">
  8. <script>
  9. myFunction();
  10. function myFunction() {
  11. var carName = "保时捷";
  12. document.getElementById("demo1").innerHTML =
  13. typeof carName + " " + carName;
  14. }
  15. document.getElementById("demo2").innerHTML =
  16. typeof carName;
  17. </script>
  18. </body>
  19. </html>

局部变量只能在它们被声明的函数内访问。


JavaScript 块作用域

通过 var 关键词声明的变量没有块作用域

在块 {} 内声明的变量可以从块之外进行访问。

  1. {
  2. var x = 10;
  3. }
  4. // 此处可以使用 x

在 ES2015 之前,JavaScript 是没有块作用域的。

可以使用 let 关键词声明拥有块作用域的变量。

在块 {} 内声明的变量无法从块外访问:

  1. {
  2. let x = 10;
  3. }
  4. // 此处不可以使用 x

重新声明变量

使用 var 关键字重新声明变量会带来问题。

在块中重新声明变量也将重新声明块外的变量:

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h1>使用 var 声明变量</h1>
  5. <p id="demo">
  6. <script>
  7. var x = 10;
  8. // Here x is 10
  9. {
  10. var x = 2;
  11. // Here x is 2
  12. }
  13. // Here x is 2
  14. document.getElementById("demo").innerHTML = x;
  15. </script>
  16. </body>
  17. </html>

使用 let 关键字重新声明变量可以解决这个问题。

在块中重新声明变量不会重新声明块外的变量:

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h1>使用 let 声明变量</h1>
  5. <p id="demo">
  6. <script>
  7. var x = 10;
  8. // Here x is 10
  9. {
  10. let x = 2;
  11. // Here x is 2
  12. }
  13. // Here x is 10
  14. document.getElementById("demo").innerHTML = x;
  15. </script>
  16. </body>
  17. </html>

浏览器支持

Internet Explorer 11 或更早的版本不完全支持 let 关键词。下表定义了第一个完全支持 let 关键词的浏览器版本:

关键词
LetChrome 49IE / Edge 12Firefox 44Safari 11Opera 36
2016 年 3 月2015 年 7 月2015 年 1 月2017 年 9 月2016 年 3 月

循环作用域

在循环中使用 var

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h1>JavaScript let</h1>
  5. <p id="demo">
  6. <script>
  7. var i = 5;
  8. for (var i = 0; i < 10; i++) {
  9. // 一些语句
  10. }
  11. document.getElementById("demo").innerHTML = i;
  12. </script>
  13. </body>
  14. </html>

在循环中使用 let

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h1>JavaScript let</h1>
  5. <p id="demo">
  6. <script>
  7. let i = 5;
  8. for (let i = 0; i < 10; i++) {
  9. // 一些语句
  10. }
  11. document.getElementById("demo").innerHTML = i;
  12. </script>
  13. </body>
  14. </html>

在第一个例子中,在循环中使用的变量使用 var 重新声明了循环之外的变量。

在第二个例子中,在循环中使用的变量使用 let 并没有重新声明循环外的变量。

如果在循环中用 let 声明了变量 i,那么只有在循环内,变量 i 才是可见的。


函数作用域

在函数内声明变量时,使用 varlet 很相似。

它们都有函数作用域

  1. function myFunction() {
  2. var carName = "保时捷"; // 函数作用域
  3. }
  4. function myFunction() {
  5. let carName = "保时捷"; // 函数作用域
  6. }

全局作用域

如果在块外声明声明,那么 varlet 也很相似。

它们都拥有全局作用域

  1. var x = 10; // 全局作用域
  2. let y = 6; // 全局作用域

HTML 中的全局变量

使用 JavaScript 的情况下,全局作用域是 JavaScript 环境。

在 HTML 中,全局作用域是 window 对象。

通过 var 关键词定义的全局变量属于 window 对象:

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h1>JavaScript 全局变量</h1>
  5. <p>在 HTML 中,通过 <b>var</b> 定义的全局变量会成为 window 变量。</p>
  6. <p id="demo">
  7. <script>
  8. var carName = "Audi";
  9. // 此处的代码能够使用 window.carName
  10. document.getElementById("demo").innerHTML = "我可以显示 " + window.carName;
  11. </script>
  12. </body>
  13. </html>

通过 let 关键词定义的全局变量不属于 window 对象:

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h1>JavaScript 全局变量</h1>
  5. <p>在 HTML 中,由 <b>let</b> 定义的全局变量,不会成为 window 变量。</p>
  6. <p id="demo">
  7. <script>
  8. let carName = "保时捷";
  9. // 此处的代码能够使用 window.carName
  10. document.getElementById("demo").innerHTML = "我不能显示 " + window.carName;
  11. </script>
  12. </body>
  13. </html>

重新声明

允许在程序的任何位置使用 var 重新声明 JavaScript 变量:

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h1>JavaScript let</h1>
  5. <p>在程序的任何位置都允许使用 <b>var</b> 重新声明JavaScript变量:</p>
  6. <p id="demo">
  7. <script>
  8. var x = 2;
  9. // 此时 x 是 2
  10. var x = 3;
  11. // 此时 x 是 3
  12. document.getElementById("demo").innerHTML = x;
  13. </script>
  14. </body>
  15. </html>

在相同的作用域,或在相同的块中,通过 let 重新声明一个 var 变量是不允许的:

  1. var x = 10; // 允许
  2. let x = 6; // 不允许
  3. {
  4. var x = 10; // 允许
  5. let x = 6; // 不允许
  6. }

在相同的作用域,或在相同的块中,通过 let 重新声明一个 let 变量是不允许的:

  1. let x = 10; // 允许
  2. let x = 6; // 不允许
  3. {
  4. let x = 10; // 允许
  5. let x = 6; // 不允许
  6. }

在相同的作用域,或在相同的块中,通过 var 重新声明一个 let 变量是不允许的:

  1. let x = 10; // 允许
  2. var x = 6; // 不允许
  3. {
  4. let x = 10; // 允许
  5. var x = 6; // 不允许
  6. }

在不同的作用域或块中,通过 let 重新声明变量是允许的:

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h1>JavaScript let</h1>
  5. <p>使用 <b>let</b>,在另一个作用域或另一个块中重新声明变量是允许的:</p>
  6. <p id="demo">
  7. <script>
  8. let x = 2; // 允许
  9. {
  10. let x = 3; // 允许
  11. }
  12. {
  13. let x = 4; // 允许
  14. }
  15. document.getElementById("demo").innerHTML = x;
  16. </script>
  17. </body>
  18. </html>