JavaScript: JavaScript 变量

变量是装数据的盒子——你给盒子贴个名字标签,随时往里放数据、取数据、换数据。

1. 什么是变量

想象你有一排贴着标签的盒子:一个叫"姓名"装着"张三",一个叫"年龄"装着 25。盒子里的东西可以换,标签不变——这就是变量。

在 JS 中,你用声明关键字(var / let / const)创建变量,用等号赋值:

HTML
<script>
var name = "张三";
let age = 25;
const PI = 3.14;
</script>

▶ 示例

JAVASCRIPT
// 本节代码示例
const message = "你好,世界!";
console.log(message);
▶ 试一试

这是最简单的示例,后续章节会详细解释。## 2. var 的问题

var 是 ES6 之前唯一的声明方式,它有两个让人头疼的特性:

  1. 函数作用域——在 iffor 里用 var 声明的变量,外面也能访问到,这不符合直觉
  2. 变量提升——var 声明会被"提升"到作用域顶部,赋值不会提升。你可以在声明前使用变量(值为 undefined),不会报错但容易误判

这两个特性让 var 成为 bug 的温床。现代 JS 中,var 基本已经被 letconst 取代。


3. let — 块级作用域,推荐首选

let 在 ES6(2015)中引入,修复了 var 的两个问题:

日常开发中,需要重新赋值的变量用 let


4. const — 常量,不可重新赋值

const 也是块级作用域,但声明时必须赋值,且之后不能再重新赋值。

注意:const 限制的是"不能重新赋值",不是"不能修改"。如果 const 装的是对象或数组,你可以修改对象属性或数组元素,只是不能把这个变量指向另一个对象。

能用 const 就用 const,需要变的时候再用 let——这是最佳实践。


5. 变量命名规则


6. 同时声明多个变量

你可以用逗号分隔,一次性声明多个变量:

HTML
<script>
let a = 1, b = 2, c = 3;
</script>

不过为了可读性,建议每行一个变量。

▶ 示例:var 的变量提升和函数作用域

HTML 📖 仅展示
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>JS 变量 - var 的问题</title>
  <style>
    body { font-family: "Microsoft YaHei", sans-serif; max-width: 550px; margin: 60px auto; }
    .warn { background: #fff3e0; padding: 12px; border-radius: 8px; color: #E65100; border-left: 4px solid #FF9800; margin: 12px 0; }
    .result { background: #f5f5f5; padding: 16px; border-radius: 8px; font-family: Consolas, monospace; line-height: 1.8; margin: 12px 0; }
    button { padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #FF9800; margin: 6px; }
    button:hover { background: #F57C00; }
  </style>
</head>
<body>
  <h2>var 的问题演示</h2>
  <p class="warn">⚠️ var 有变量提升和函数作用域问题,实际开发中避免使用</p>
  <button id="hoistBtn">演示:变量提升</button>
  <button id="scopeBtn">演示:函数作用域泄漏</button>
  <div class="result" id="output">点击按钮查看结果</div>
  <script>
    document.getElementById("hoistBtn").onclick = function() {
      var output = "";
      output += "使用 var 声明前访问:x = " + typeof x + "\n";
      var x = 10;
      output += "声明后访问:x = " + x + "\n\n";
      output += "👆 变量提升导致声明前不报错,值为 undefined\n";
      output += "这在大型项目中很容易引发 bug!";
      document.getElementById("output").textContent = output;
    };
    document.getElementById("scopeBtn").onclick = function() {
      var output = "";
      for (var i = 0; i < 3; i++) {
        // var i 泄漏到循环外部
      }
      output += "循环结束后,i = " + i + "\n\n";
      output += "👆 var i 泄漏到循环外部了!\n";
      output += "如果用 let i,循环外就访问不到";
      document.getElementById("output").textContent = output;
    };
  </script>
</body>
</html>
逻辑代码 41 行(超过 40 行限制,仅展示)

▶ 示例:let 的块级作用域

HTML 📖 仅展示
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>JS 变量 - let 块级作用域</title>
  <style>
    body { font-family: "Microsoft YaHei", sans-serif; max-width: 550px; margin: 60px auto; }
    .good { background: #e8f5e9; padding: 12px; border-radius: 8px; color: #2E7D32; border-left: 4px solid #4CAF50; margin: 12px 0; }
    .result { background: #f5f5f5; padding: 16px; border-radius: 8px; font-family: Consolas, monospace; line-height: 1.8; margin: 12px 0; }
    button { padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #4CAF50; margin: 6px; }
    button:hover { background: #388E3C; }
  </style>
</head>
<body>
  <h2>let 块级作用域演示</h2>
  <p class="good">✅ let 有块级作用域,出了 {} 就访问不到,更安全</p>
  <button id="letScopeBtn">演示:let 块级作用域</button>
  <button id="letLoopBtn">演示:let 在循环中</button>
  <div class="result" id="output">点击按钮查看结果</div>
  <script>
    document.getElementById("letScopeBtn").onclick = function() {
      let output = "块级作用域测试:\n";
      let x = 100;
      output += "外层 x = " + x + "\n";
      {
        let x = 200;
        output += "内层 x = " + x + "\n";
      }
      output += "出块后 x = " + x + "\n\n";
      output += "👆 内外层的 x 互不影响,各自独立";
      document.getElementById("output").textContent = output;
    };
    document.getElementById("letLoopBtn").onclick = function() {
      let output = "let 在循环中:\n";
      for (let i = 0; i < 3; i++) {
        output += "循环内 i = " + i + "\n";
      }
      output += "\n";
      try {
        output += "循环外 i = " + i;
      } catch(e) {
        output += "循环外访问 i → 报错:" + e.message;
      }
      output += "\n\n👆 let i 被限制在循环内,不会泄漏到外部";
      document.getElementById("output").textContent = output;
    };
  </script>
</body>
</html>
逻辑代码 49 行(超过 40 行限制,仅展示)

▶ 示例:const 常量

HTML 📖 仅展示
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>JS 变量 - const 常量</title>
  <style>
    body { font-family: "Microsoft YaHei", sans-serif; max-width: 550px; margin: 60px auto; }
    .tip { background: #e3f2fd; padding: 12px; border-radius: 8px; color: #1565C0; border-left: 4px solid #2196F3; margin: 12px 0; }
    .result { background: #f5f5f5; padding: 16px; border-radius: 8px; font-family: Consolas, monospace; line-height: 1.8; margin: 12px 0; }
    button { padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; margin: 6px; }
    #constBtn { background: #9C27B0; }
    #objectBtn { background: #2196F3; }
  </style>
</head>
<body>
  <h2>const 常量演示</h2>
  <p class="tip">💡 const 声明后不能重新赋值,但对象和数组的属性/元素可以修改</p>
  <button id="constBtn">演示:const 不可重赋值</button>
  <button id="objectBtn">演示:const 修改对象属性</button>
  <div class="result" id="output">点击按钮查看结果</div>
  <script>
    document.getElementById("constBtn").onclick = function() {
      const PI = 3.14159;
      let output = "const PI = " + PI + "\n\n";
      output += "尝试重新赋值 PI = 3.14:\n";
      try {
        PI = 3.14;
      } catch(e) {
        output += "❌ 报错:" + e.message;
      }
      output += "\n\n👆 const 变量一旦赋值就不能再改";
      document.getElementById("output").textContent = output;
    };
    document.getElementById("objectBtn").onclick = function() {
      const person = { name: "张三", age: 25 };
      let output = "const person = " + JSON.stringify(person) + "\n\n";
      output += "修改 person.age = 26:\n";
      person.age = 26;
      output += "person = " + JSON.stringify(person) + "\n\n";
      output += "添加 person.city = '北京':\n";
      person.city = "北京";
      output += "person = " + JSON.stringify(person) + "\n\n";
      output += "👆 const 限制的是变量指向,不是对象内容\n";
      output += "就像 const 盒子锁定了标签,但盒子里东西可以换";
      document.getElementById("output").textContent = output;
    };
  </script>
</body>
</html>
逻辑代码 47 行(超过 40 行限制,仅展示)

▶ 示例:var / let / const 对比

HTML 📖 仅展示
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>JS 变量 - 三种声明对比</title>
  <style>
    body { font-family: "Microsoft YaHei", sans-serif; max-width: 600px; margin: 60px auto; }
    table { width: 100%; border-collapse: collapse; margin: 16px 0; }
    th, td { padding: 10px; text-align: center; border: 1px solid #ddd; }
    th { background: #2196F3; color: #fff; }
    .bad { color: #f44336; }
    .good { color: #4CAF50; font-weight: bold; }
    button { margin-top: 12px; padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; color: #fff; background: #e91e63; }
    #result { margin-top: 12px; padding: 16px; background: #f5f5f5; border-radius: 8px; font-family: Consolas, monospace; line-height: 1.8; }
  </style>
</head>
<body>
  <h2>var / let / const 对比</h2>
  <table>
    <tr><th>特性</th><th>var</th><th>let</th><th>const</th></tr>
    <tr><td>作用域</td><td class="bad">函数作用域</td><td class="good">块级作用域</td><td class="good">块级作用域</td></tr>
    <tr><td>变量提升</td><td class="bad">是(值为undefined)</td><td class="good">否(暂时性死区)</td><td class="good">否(暂时性死区)</td></tr>
    <tr><td>可否重新赋值</td><td class="bad">是</td><td>是</td><td class="bad">否</td></tr>
    <tr><td>声明前使用</td><td class="bad">不报错</td><td class="good">报错</td><td class="good">报错</td></tr>
    <tr><td>推荐程度</td><td class="bad">避免使用</td><td class="good">推荐</td><td class="good">首选</td></tr>
  </table>
  <button id="testBtn">运行对比测试</button>
  <div id="result"></div>
  <script>
    document.getElementById("testBtn").onclick = function() {
      var output = "=== 对比测试 ===\n\n";
      output += "【var】函数作用域:\n";
      for (var i = 0; i < 3; i++) {}
      output += "循环外 var i = " + i + "(泄漏了)\n\n";
      output += "【let】块级作用域:\n";
      for (let j = 0; j < 3; j++) {}
      try {
        output += "循环外 let j = " + j;
      } catch(e) {
        output += "循环外访问 let j → " + e.message + "(正确行为)";
      }
      output += "\n\n【const】不可重赋值:\n";
      const MAX = 100;
      output += "const MAX = " + MAX + "\n";
      try {
        MAX = 200;
      } catch(e) {
        output += "重赋值 → " + e.message + "(正确行为)";
      }
      output += "\n\n结论:const > let >> var";
      document.getElementById("result").textContent = output;
    };
  </script>
</body>
</html>
逻辑代码 54 行(超过 40 行限制,仅展示)

❓ 常见问题

Q const 声明的对象属性可以修改,那 const 有什么意义?
A const 保证变量指向不变——你不会意外地把 person 重新指向另一个对象,但修改已有对象的属性是合理的。就像你锁定了盒子上的标签(这个盒子永远叫"张三的盒子"),但往盒子里放什么、换什么都可以。
Q 什么时候用 let,什么时候用 const?
A 简单判断法:声明时问自己"这个值以后会变吗?"——不会就用 const,会变就用 let。比如计数器用 let,配置常量用 const。绝大多数场景 const 就够了,你会发现自己用 const 的频率远高于 let。
Q var 完全不能用吗?
A 技术上能用,但没必要。let 和 const 是 var 的全面升级版,没有任何场景必须用 var 而不能用 let/const。老代码里看到 var 能看懂就行,新代码一律用 let/const。

📖 小节

📝 作业

  1. 基础题:用 const 声明一个常量 SITE_NAME 赋值为你的名字,用 let 声明一个变量 visitCount 赋值为 0,然后在页面上显示这两个值。
  2. 进阶题:创建一个页面,用一个按钮模拟"访问计数"——每次点击按钮让 visitCount 加 1 并显示当前值,体会 let 可重新赋值而 const 不行的区别。
  3. 挑战题:创建一个页面,用 const 声明一个学生对象 { name: "张三", scores: [80, 90, 75] },然后实现:添加一个新成绩 85、计算平均分、修改名字为"李四",全程 const 不变,验证对象内容可以修改。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏