JavaScript青少年简明教程:语法基础
JavaScript 是一种轻量级的、解释型的或即时编译型的编程语言。本节介绍JavaScript的标识符、变量、常量知识。
标识符(Identifiers)
标识符是用来命名变量、常量、函数、类等的名字。它们必须符合一定的规范。
规则
只能包含字母(a-z,A-Z)、数字(0-9)、下划线(_)和美元符号($)。
不能以数字开头。
区分大小写。
不能使用JavaScript中的保留字或关键字:例如,var、function、for、while 等都是关键字,不能用作标识符。
在JavaScript中,标识符可以使用Unicode字符,包括汉字(中文字符)。例如,可以使用汉字作为标识符,考虑到代码的可读性、可维护性和可移植性,通常并不推荐。
【JavaScript关键字(Keywords)
关键字是 JavaScript 语言保留的字,具有特殊意义。部分常见的关键字如下:
控制语句:if、else、switch、case、default
循环语句:for、while、do、break、continue
声明语句:var、let、const、function、class
错误处理:throw、try、catch、finally
其他:return、void、delete、typeof、new、in、instanceof】
有效的标识符
let myVariable;
let _myVariable;
const $myVariable = 42;
let variable123;
无效的标识符
let 123variable; // 不能以数字开头
let my-variable; // 不能包含连字符
JavaScript注释
JavaScript注释有两种方式:单行注释和多行注释。“//”表示单行注释,从“//”开始到当前行的末尾都是注释的内容。“/*”和“*/”表示多行注释,从“/*”开始到“*/”结束,中间的内容都是注释。
JavaScript 是区分大小写的或者说“大小写敏感”,并使用 Unicode 字符集。
编程语言中的“大小写敏感”意味着该语言在识别标识符、关键字或者其他语法元素时,会区分字母的大小写。在这种语言中,大写字母和小写字母被视为不同的字符,因此,同一个词或标识符的大写形式和小写形式将代表不同的含义或者是完全不同的变量。例如在大小写敏感的编程语言如C、C++、Java、JavaScript和Python中,变量myVariable和myvariable是两个完全不同的变量。
【顺便提示:
HTML(Hyper Text Markup Language:超文本标记语言)是一种标记语言,用于创建网页内容。在HTML中,标签名和属性名是不区分大小写的,例如<body>和<BODY>在HTML中是等效的。
CSS(Cascading Style Sheets)在大多数情况下是不区分大小写的。但在处理具体值(如URL或字体名称)时,需要注意URL中的路径和文件名是区分大小写的,这取决于服务器的设置。font-family属性的值涉及到对字体文件名的引用,需要注意,不同的操作系统通常使用不同类型的文件系统,它们对大小写的敏感性也有所不同。例如,大多数基于Unix的系统,包括Linux,使用的文件系统(如ext3, ext4, XFS, Btrfs等)通常是区分大小写的。Windows使用的文件系统(如FAT32, exFAT, NTFS)通常不区分大小写。】
变量(Variables)
变量(variable)是值的具名引用。https://developer.mozilla.org/zh-CN/docs/Glossary/Variable
它存放的数值是可以改变的,也就是变量指程序运行过程中可以发生改变的量。
【A variable is a named reference to a value. That way an unpredictable value can be accessed through a predetermined name.
变量是对值的命名引用。这样,就可以通过预定的名称访问不可预测的值。
不可预测的值 (Unpredictable value): 指在程序的执行过程中值可能会改变——因为它们可以根据不同的条件或输入发生变化。
引用 (Reference): 变量不直接存储值,而是存储值的引用或地址。但在这个语境下,我们可以简化为变量“指向”或“关联”一个值。】
变量是程序中用于访问和操作特定内存位置的符号表示。在应用程序中,变量作为值的符号名称。
在JavaScript中,可以使用var、let或const关键字来声明变量。var关键字是旧版本的声明方式,let和const是ES6引入的新的声明方式,let用于声明可变的变量,而const用于声明不可变的常量——const 声明创建的变量不能重新赋值。在JavaScript中,如果你试图使用一个未声明的变量,那么会得到一个错误。但是,如果你试图访问一个已经声明但未赋值的变量,那么会得到undefined。
在新的JavaScript项目中,let和const是更好的选择。
JavaScript是一种动态类型语言,这意味着你不需要提前声明变量的类型。你可以创建一个变量并为其赋予一个字符串,然后再将其改为数字。
let variable = "Hello, World!";
variable = 42;
变量可以在声明时初始化,也可以先声明后赋值。
let x = 10; // 在声明时初始化(赋初值)
let age; // 声明一个变量
age = 25; // 后续赋值
变量一旦被赋值,可以在函数计算、条件判断、循环或其他表达式中使用。
JavaScript 是一种弱类型或动态类型语言,这意味着在声明变量时不需要指定数据类型,同一变量可以在其生命周期内重新赋值为不同类型的值。例如:
let data = 10; // 赋初值为整数
data = "ten"; // 稍后被赋为字符串
在一条语句中可以声明多个变量。使用逗号将变量分隔开,可以同时对它们进行初始化。以下是一个示例:
let a = 1, b = 2, c = 3;
不过在实际开发中,为了提高代码的可读性,通常会将每个变量单独声明在不同的行中。
变量的赋值,指的是将值和变量关联起来,以便在程序的后续部分中使用或修改该值。
JavaScript作为动态类型语言的一个重要体现,同一个变量可以在不同时刻存储不同类型的数据,而不会产生错误。【这与静态类型语言(如Java或C++)不同,在那些语言中,变量的类型一旦声明就不能改变。】
示例:
let x = 5; // x 现在是一个数字
console.log(typeof x); // 输出: "number"
x = "Hello"; // x 现在变成了一个字符串
console.log(typeof x); // 输出: "string"
x = true; // x 现在又变成了一个布尔值
console.log(typeof x); // 输出: "boolean"
x = { name: "Alice" }; // x 现在是一个对象
console.log(typeof x); // 输出: "object"
尽管JavaScript允许这种做法,但在实际编程中,通常建议保持变量类型的一致性,以提高代码的可读性和可维护性。
const 声明创建的变量不能重新赋值:
const studentName = "Frank";
console.log(studentName); // 输出:Frank
studentName = "Suzy"; //抛出错误:TypeError
在JavaScript中,var、let和const称为变量声明符(或称为变量声明关键字),它们有特定的用途和语义。
与 var 相比,let 和 const 提供了更加严格的作用域控制。var 声明的变量会被提升至函数或全局作用域顶部,而 let 和 const 声明的变量被局限于块级作用域(例如循环、条件判定等)。
const 声明用于创建常量或不可重新赋值的变量,对于对象和数组,const 只保证引用不可变,不保证内容不可变。
【特别提示,这里提到了函数,因此简单介绍几句,简单地说,函数(function)是可以重复调用的代码块,函数可以接受参数,返回值,并且可以被调用多次。函数的基本结构如下:
function 函数名(参数1, 参数2, ...) {
// 函数体——一系列语句
}
在此了解即可,以后在“函数”一节还将介绍。】
JavaScript语言,变量不是必须先声明才能使用,但推荐先声明再使用。
为何变量不是必须先声明就能使用?
变量提升(Variable Hoisting)
变量提升是 JavaScript 中的一种机制,其中变量和函数声明在编译阶段被移动到它们各自作用域的顶部。这意味着即使声明可能在代码中出现在使用它们的代码之后,变量和函数仍然可以使用。
使用 var 声明的变量会被提升,但只是声明被提升,初始化不会被提升。如果在声明前使用这种变量,它会被解释为 undefined。
使用 let 声明的变量也被提升,但它们并不像 var 那样在声明前就可以访问。尝试访问它们会导致一个报错(ReferenceError),因为它们存在于 "暂时性死区" 直到它们的声明被执行。
严格模式(Strict Mode)
严格模式是一种在 JavaScript 中可选的更严格的错误检查模式。启用严格模式可以通过在脚本或函数的顶部添加 "use strict"; 来实现。在严格模式下,JavaScript 的某些行为会被改变,以便提升异常处理和错误检测。
在严格模式中,如果你使用未声明的变量,JavaScript 会抛出一个错误,而不是像在非严格模式下那样隐式地创建一个全局变量。
"use strict";
console.log(b); // ReferenceError: b is not defined
var b = 20;
为何推荐先声明再使用?
推荐在JavaScript中先声明变量然后再使用它们,有几个重要的原因:
代码可读性:先声明变量可以使代码更易于阅读和理解。读者可以清楚地看到哪些变量正在被使用以及它们的预期用途。
避免意外的全局变量:在非严格模式下,如果你忘记使用var、let来声明一个变量,在函数内部创建的变量将默认为全局变量。这可能导致意外的命名冲突和难以追踪的错误。通过先声明变量,你可以确保变量在预期的作用域内。
严格模式兼容性:在严格模式下(通过添加"use strict";指令),尝试访问未声明的变量会导致ReferenceError。通过先声明变量,你可以确保你的代码与严格模式兼容,从而更容易捕获潜在的错误。
关于 var 的说明:
作用域:var 声明的变量具有函数作用域或全局作用域。这意味着变量在声明它的函数内部或全局范围内可见。
变量提升:使用 var 声明的变量会被提升到其作用域的顶部。这意味着你可以在变量声明之前使用该变量,但它的值会是 undefined。只有变量声明会被提升,而变量的初始化不会被提升。
重复声明:在同一个作用域内,var 允许重复声明同一个变量。这意味着你可以在同一个作用域内多次使用 var 来声明同一个变量,而不会引发错误。后续的声明会覆盖前面的声明。
示例:
function example() { var x = 10; console.log(x); // 输出 10 if (true) { var x = 20; // 同一个作用域内,变量效果被覆盖 console.log(x); // 输出 20 } console.log(x); // 输出 20(受到了 if 块内的影响) } example(); //调用
上面的示例中,var x = 20 覆盖了外部作用域中的 var x = 10,因此最后输出的值是 20。需要注意的是,var 声明的变量没有块级作用域,所以在 if 块中声明的变量可以在外部作用域中访问到。
关于let 的说明:
作用域:let 声明的变量具有块级作用域。这意味着变量在其声明的块(由 {} 包围)内部可见,并且在块外不可见。
变量提升:使用 let 声明的变量也会被提升到其作用域的顶部,但与 var 不同的是,在变量声明之前使用它会导致一个称为“暂时性死区”(Temporal Dead Zone,TDZ)的错误。换句话说,你不能在声明之前引用该变量。
重复声明:在同一个作用域内,let 不允许重复声明同一个变量。如果你尝试在同一个作用域内多次使用 let 来声明同一个变量,会引发语法错误。
示例:
function example() { let x = 10; console.log(x); // 输出 10 if (true) { let x = 20; // 块级作用域内的新变量 console.log(x); // 输出 20 } console.log(x); // 输出 10(受到了块级作用域的保护) } example();//函数调用
上面的示例中,let x = 20 只在 if 块内部有效,因此外部作用域中的 let x = 10 不受影响,最后输出的值是 10。
“暂时性死区”(Temporal Dead Zone,TDZ)是 let 和 const 声明的变量在其声明之前不可访问的状态,这意味着在声明之前访问这些变量会导致引用错误(ReferenceError)。这一特性帮助开发者避免在变量初始化前意外使用未定义的变量,从而提升代码的可靠性和可维护性。
例如:
console.log(a); // ReferenceError: Cannot access 'a' before initialization
let a = 10;
console.log(b); // ReferenceError: Cannot access 'b' before initialization
const b = 20;
与 let 和 const 不同,var 声明的变量不存在 TDZ:
console.log(c); // undefined
var c = 30;
在这里,c 被提升(hoisted),并初始化为 undefined,因此在声明之前访问不会抛出错误。
关于暂时性死区的示例:
function tdzExample() { console.log(x); // ReferenceError: Cannot access 'x' before initialization let x = 10; } tdzExample();
上面的示例中,由于 let 声明的变量 x 存在暂时性死区,在 let x = 10 之前引用 x 会引发引用错误。
在 JavaScript 中,可以声明一个不带 var、let 或 const 的变量。这种声明会创建一个全局变量(如果是在全局作用域中)或者隐式地绑定到当前作用域的变量(如果是在函数内部)。这种做法被认为是不好的编程实践,因为它会导致难以维护和调试的代码。例:
function myFunction() { x = 10; // 声明一个没有 var、let 或 const 的变量 console.log(x); } myFunction(); console.log(x); // 输出 10,因为 x 被声明为全局变量
上面的例子中,x 在 myFunction 函数中被声明,但由于没有使用 var、let 或 const,它被隐式地声明为全局变量。因此,即使在函数外部也能访问到 x。
为了防止这种潜在的错误,可以使用严格模式("use strict")。严格模式下,尝试声明一个没有 var、let 或 const 的变量会抛出错误。
严格模式通过在脚本或函数的开头添加 "use strict" 来启用,可以帮助捕捉错误并强制更严格的语法要求,提升代码质量和可维护性。例:
"use strict"; function myFunction() { x = 10; // 会抛出错误:ReferenceError: x is not defined console.log(x); } myFunction();
上面的例子表明,严格模式下,尝试声明一个没有 var、let 或 const 的变量会抛出错误。
常量(Constants)
使用 const 声明常量,要求在声明的同时必须进行初始化,否则会报错。
常量(Constants)用来存储不可更改的数据,通过 const 声明,声明时必须初始化,且不可重新赋值,但对象或数组的内部属性或元素可以修改。
关于 const 的说明:
作用域:const 声明的变量具有块级作用域。这意味着常量在其声明的块(由 {} 包围)内部可见,并且在块外不可见。
重复声明:在同一个作用域内,const 不允许重复声明同一个常量。如果你尝试在同一个作用域内多次使用 const 来声明同一个常量,会引发语法错误。
不可重新赋值:使用 const 声明的常量必须在声明时进行初始化,并且一旦赋值之后,不能再更改其值。然而,对于对象或数组,虽然不能重新赋值,但可以修改其内部的属性或元素——对于对象和数组,const 只保证引用不可变,不保证内容不可变。
示例
function example() { const x = 10; console.log(x); // 输出 10 if (true) { const x = 20; // 块级作用域内的新常量 console.log(x); // 输出 20 } console.log(x); // 输出 10(受到了块级作用域的保护) } example();
上面的示例中,const x = 20 只在 if 块内部有效,因此外部作用域中的 const x = 10 不受影响,最后输出的值是 10。
不可重新赋值的示例:
const y = 30;
y = 40; // 报错:TypeError: Assignment to constant variable.
对于对象或数组,可以修改其内部属性或元素:
const obj = { a: 1 };
obj.a = 2; // 这是允许的
console.log(obj.a); // 输出 2
const arr = [1, 2, 3];
arr.push(4); // 这是允许的
console.log(arr); // 输出 [1, 2, 3, 4]
上面的示例中,虽然 obj 和 arr 是用 const 声明的,但我们仍然可以修改对象的属性和数组的元素。