跟着 MDN 学JavaScript day_4:如何存储你需要的信息——变量
引言
在探索了 JavaScript 的宏观世界,了解了它能做什么、如何与 Web 技术协同工作之后,我们现在将目光收回到最微观、最基础的构建单元上。这篇文章是 JavaScript 基础知识的真正起点,我们将深入剖析变量的概念。如果说编程是构建数字世界的魔法,那么变量就是承载这些魔法的基本容器。不理解变量,就无法编写任何有意义的程序。本文将带你从零开始,掌握在 JavaScript 中声明、初始化、更新和使用变量的所有核心知识,并厘清一些常见的误区。学习完本文,你将能够自信地在代码中创建和操纵数据,为后续更复杂的学习打下坚实的地基。
一、搭建你的实验环境:需要的工具
理论的学习离不开实践的检验。在开始深入变量之前,我们需要准备好编程的环境。对于初学者而言,最触手可及的工具就是 Web 浏览器内置的开发者控制台。你可以在大多数桌面浏览器中通过按 F12 键或 Ctrl+Shift+I (Windows/Linux) / Cmd+Option+I (Mac) 打开它,然后找到 “Console” (控制台) 标签页。在这个控制台中,你可以直接输入和执行 JavaScript 代码,并立即看到结果,这是进行小块代码测试和验证概念的绝佳场所。
除了使用浏览器自带的控制台,本文也在页面中嵌入了一个简易的 JavaScript 终端,你可以直接在下方带有“运行”标志的代码块中编写和测试代码。这种即时反馈的学习方式能极大提高效率,帮助你直观地看到每一行代码产生的影响。在接下来的所有例子中,请随时尝试运行和修改代码,亲手敲下每一个字符,这是将知识内化为技能的唯一途径。
二、变量是什么:存放数值的容器
变量,从字面意义上理解,就是“可以改变的量”。在 JavaScript 中,一个变量就是一个用于存放数值的容器。这个“数值”的概念非常广泛,它可以是一个用于累加计算的数字,可以是一段问候语的字符串,也可以是更复杂的数据结构,甚至是一个函数。变量的独特性和核心价值就在于它存放的数值是可以改变的,这也是它区别于“常量”的根本特征。
让我们通过一个简单的例子来直观地理解它。点击下面的按钮,第一行代码会在屏幕上弹出一个对话框,让你输入名字,然后将你输入的名字存储到变量 name 中。第二行代码会读取这个变量,并显示一段包含你名字的欢迎信息。
<button>Press me</button>javascript const button = document.querySelector("button"); button.onclick = function () { let name = prompt("What is your name?"); alert("Hello " + name + ", nice to see you!"); };现在,让我们做一个思维实验:如果没有变量,上面这个功能该如何实现?我们不得不用无穷无尽的 if…else if 语句来枚举每一个可能的输入。
letname=prompt('What is your name?');if(name==='Adam'){alert('Hello Adam, nice to see you!');}elseif(name==='Alan'){alert('Hello Alan, nice to see you!');}elseif(name==='Bella'){alert('Hello Bella, nice to see you!');}elseif(name==='Bianca'){alert('Hello Bianca, nice to see you!');}elseif(name==='Chris'){alert('Hello Chris, nice to see you!');}// ... and so on ...你可能暂时还不能完全理解这段代码的语法,但逻辑是清晰的:为了处理一个本应简单灵活的功能,我们需要编写大量死板、低效且无法覆盖所有情况的代码。这清晰地展示了变量的力量。它就像一个贴了标签的纸箱子,你可以把任何东西放进去,需要时再取出来,并且可以随时更换里面的东西。这个比喻非常关键:变量不是数值本身,它仅仅是用于存储数值的容器。区分“容器”和“内容物”是理解后续所有相关概念的基础。
三、声明变量:创造一个空箱子
要想使用一个纸箱子,第一步是拿到一个箱子,并给它贴上标签。在 JavaScript 中,这个过程叫做声明变量。声明一个变量的语法非常简单:使用关键字 let 或 var,后跟变量的名字。
letmyName;letmyAge;在这里,我们声明了 myName 和 myAge 两个变量。此刻,它们就像是两个刚刚贴好标签的空箱子,存在于内存中,但内部是空的。你可以直接在控制台中输入变量名来验证它的状态。
myName;myAge;执行上面的代码,控制台会返回 undefined。这是一个重要的特殊值,它明确表示“变量存在,但没有被赋值”。你必须严格区分 undefined 和 “变量不存在”这两种情况。如果你尝试访问一个从未声明过的变量,比如输入 scoobyDoo;,浏览器将会抛出一个引用错误 ReferenceError,提示你这个变量未被定义。回到纸箱子的比喻,undefined 意味着你拥有一个有标签的空箱子,而 ReferenceError 则意味着根本没有这个箱子,这个标签所指的东西不存在。这是编程新手非常容易混淆的一个点,请务必理解透彻。
四、初始化变量:给箱子装上东西
声明了一个空箱子之后,我们自然想把东西放进去。这个过程叫做变量的初始化。方法是在变量名之后跟上一个等号 =,然后再跟上要存储的数值。
myName="Chris";myAge=37;现在,这两个变量不再为空,它们分别存储了字符串 “Chris” 和数字 37。你可以再次在控制台中输入变量名来确认其内容。
myName;myAge;为了更高效,我们通常会将声明和初始化这两个步骤合并在一条语句中完成。
letmyName="Chris";这是你在未来会最常使用的模式,因为它简洁明了。在程序结构上,还有一个值得注意的概念叫做“顶置”。在一个多行代码的 JavaScript 程序中,你甚至可以在初始化变量之后再声明它,程序依然可以工作。这是因为变量的声明会在代码执行之前被“顶置”到其作用域的顶部。但这通常不是一个好的实践,它会使代码的逻辑流程变得混乱。在接下来的 var 与 let 的区别中,我们会进一步讨论这个问题。
五、var 与 let 的区别:历史与新标准
你可能已经注意到了,声明变量有两个关键字:var 和 let。为什么会有两个?这背后是 JavaScript 的历史和发展。var 是 JavaScript 诞生之初就存在的旧语法,而 let 是 ES6 现代 JavaScript 版本中引入的新关键字。引入 let 的目的,正是为了解决 var 在设计上的一些令人困惑甚至容易导致错误的缺陷。理解它们的核心区别,对你写出健壮、可预测的代码至关重要。
第一个重要区别在于作用域和变量顶置的行为。使用 var 声明的变量具有函数作用域,并且其声明会被提升,允许你在声明语句之前就使用变量(其值为 undefined)。例如:
myName="Chris";functionlogName(){console.log(myName);}logName();varmyName;这段代码不会报错,因为 var myName 的声明被提升到了代码的最顶部。然而,使用 let 声明的变量具有块级作用域,虽然它的声明也会被提升,但它会被置于“暂时性死区”,在声明语句之前访问它会导致 ReferenceError。将上面例子中的 var 替换成 let 将立即引发一个错误。这是一个好事,因为它强制你遵循“先声明,后使用”的逻辑,避免了代码的混乱。
第二个重要区别在于重复声明。在相同作用域内,使用 var 可以多次声明同一个名称的变量而不会报错。
varmyName="Chris";varmyName="Bob";但这明显违背了编程的常理,是不必要的冗余,极易隐藏错误。而 let 则不允许这种重复声明。
letmyName="Chris";letmyName="Bob";// 此行会引发错误如果你需要使用 let 更新一个变量的值,你应该简单地省略 let 关键字:
letmyName="Chris";myName="Bob";这是非常清晰且明智的语言设计。综上所述,除非你需要维护一些非常老旧、仅支持 Internet Explorer 11 及更早版本的代码(这些环境不支持 let),否则在任何情况下,你都应该优先使用 let 而不是 var。
六、更新变量与命名规则:代码的可读性
一旦变量被初始化,它的核心魅力——“可变性”——就得以展现。更新一个变量的值极其简单,只需要再次为它赋值即可。
myName="Bob";myAge=40;你无需也不应该再次使用 let 或 var 关键字。
给变量起一个好名字,是编程中最重要却最容易被忽视的环节之一。一个清晰的命名能极大提升代码的可读性和可维护性。你需要遵循一些规则和最佳实践。首先,变量名只能包含拉丁字母(a-z, A-Z)、数字(0-9)、下划线(_)和美元符号($),但不能以数字开头。其次,变量名是大小写敏感的,myage 和 myAge 是完全不同的两个变量。
一个被广泛采用的命名约定是“小写驼峰命名法”,其规则是将第一个单词的首字母小写,之后每个单词的首字母大写。例如 myAge, initialColor, finalOutputValue。命名应简短且具有描述性,避免使用无意义的 a, b, x 或过长的句子。绝对不要使用 JavaScript 的保留字,如 var, function, let, for, return 等,因为它们已经被语言本身占用了。
好的命名示例:
age myAge init initialColor finalOutputValue audio1 audio2错误与差的命名示例:
1a _12 myageMYAGEvarDocument skjfndskjfnbdskjfb thisisareallylongstupidvariablenameman从现在开始,请有意识地为自己创建的每一个变量构思一个清晰、合规的名字。
七、变量类型:不仅仅是数字
JavaScript 中的变量可以存储多种不同类型的数据,这些类型构成了程序处理信息的基础。我们已经间接接触了其中几个。
Number 数字: 用于存储整数或浮点数。在 JavaScript 中,给数字变量赋值时,不需要用引号括起来。
letmyAge=17;letpi=3.14159;String 字符串: 字符串是文本片段。当你将值赋给一个字符串变量时,你必须用单引号或双引号将文本包起来,以此告诉解释器这不是变量名或其他代码。
letdolphinGoodbye="So long and thanks for all the fish";Boolean 布尔值: 布尔值只有两种可能的值:true 或 false。它像是代码中的开关,通常用于条件测试。
letiAmAlive=true;lettest=6<3;// 这里 test 的值将是 false,因为 6 不小于 3Array 数组: 数组是一个用于存储多个值的有序集合。它用方括号 [] 包裹,内部的值用逗号分隔。
letmyNameArray=["Chris","Bob","Jim"];letmyNumberArray=[10,15,40];// 访问数组元素需要使用从 0 开始的索引myNameArray[0];// 返回 'Chris'myNumberArray[2];// 返回 40Object 对象: 对象是对现实世界实体的代码建模。它存储的是键值对的集合,花括号 {} 包裹每个属性名和其对应的值。
letdog={name:"Spot",breed:"Dalmatian"};// 访问对象的属性使用点号 .dog.name;// 返回 'Spot'这些是 JavaScript 中最基本的数据结构,存储的所有内容,最终都会归于这些类型之一。
八、动态类型:灵活与谨慎
JavaScript 是一门“动态类型语言”。这意味着,与 Java 或 C 等静态类型语言不同,你在声明变量时无需指定它将要存储什么类型的数据。同一个变量可以根据程序的逻辑,先后被赋值为数字、字符串或任何其他类型。浏览器引擎会在运行时自动识别和处理它的类型。
letmyString="Hello";即使一个字符串内容全是数字,它依然是一个字符串,这可能会在运算时导致意想不到的结果。
letmyNumber="500";// 这是一个字符串,不是数字typeofmyNumber;// 返回 "string"myNumber=500;// 现在它被重新赋值为了一个真正的数字typeofmyNumber;// 返回 "number"我们使用 typeof 操作符来验证变量的数据类型。这种灵活性给予了开发者极大的便利,但也要求你在进行加法运算或比较操作时必须格外小心,以避免类型强制转换带来的隐蔽错误。理解并善用动态类型,是掌握 JavaScript 的关键一步。
总结
通过本文的学习,我们已经系统地掌握了 JavaScript 中变量的核心知识。我们从变量作为“数值容器”的基本概念出发,逐步学习了如何声明变量以创建容器,如何初始化变量以放入内容,以及如何更新其内部的值。我们深入探讨了 var 和 let 的关键区别,明确了在现代 JavaScript 开发中应优先使用 let。我们还学习了变量命名的规则与最佳实践,并概览了数字、字符串、布尔值、数组和对象这几种基本的数据类型。最后,我们理解了 JavaScript 作为动态类型语言的本质。变量是构建任何 JavaScript 程序的基石。在下一篇文章中,我们将聚焦于数字和数学运算,看看如何在这些容器中进行更复杂的计算和操作。
还在为 JavaScript 代码写得像“意大利面条”、逻辑混乱难以维护而头秃?收藏本文持续跟进,后续将系统分享 JS 高效语法糖、浏览器兼容与 Polyfill 实战、手写核心源码解析、常见坑点避雷指南,从基础语法到进阶逻辑一站式打通,助你快速提升前端开发硬实力!
