Skip to content

js_examples

JavaScript 是一种多功能语言,主要以使网页具有交互性而闻名。其功能包括:

  • 动态修改 HTML 内容和结构。
  • 改变 HTML 属性(例如,图片的 src 属性)。
  • 修改 CSS 样式以改变元素的显示外观。
  • 在表单提交前验证用户输入。
  • 处理用户事件,如点击、鼠标移动、按键。
  • 发送异步请求到服务器(AJAX / Fetch API),无需重新加载页面即可加载数据。
  • 使用 localStorage 或 sessionStorage 在浏览器中本地存储数据。
  • 创建动画和复杂的视觉效果。
  • 还有更多,包括服务器端开发 (Node.js)、移动应用和游戏开发。

JavaScript 可以通过多种方式显示数据:

  • window.alert("message"):显示一个简单的对话框。应谨慎使用,因为它会阻塞用户交互。
  • element.innerHTML = "html content":将 HTML 内容写入 HTML 元素。处理不可信内容时要小心,存在 XSS 风险。
  • element.textContent = "text content":将纯文本写入 HTML 元素。对于仅更新文本更安全。
  • document.write("content"):直接写入 HTML 文档流。页面加载完成后强烈不建议使用,因为它会覆盖整个文档。
  • console.log("message"):向浏览器开发者控制台写入消息。对于调试必不可少。

输出方法将在相关章节进一步解释。

JavaScript 代码可以使用 <script> 标签放置在 HTML 文档中:

  • 在 <head> 内: <script src="path/to/script.js"></script>。这里的脚本在 HTML body 解析之前被获取并执行,这可能会阻塞页面渲染。使用 defer 属性 (<script defer src="..."></script>) 可以确保脚本在 HTML 解析后但在 DOMContentLoaded 事件发生之前执行。使用 async 属性 (<script async src="..."></script>) 可以异步获取和执行脚本,不阻塞解析,但不能保证与其他异步脚本或 DOM 就绪状态相关的执行顺序。
  • 在 <body> 内: 通常放置在末尾,紧挨着 </body> 标签之前。这使得 HTML 可以先解析和渲染,因此脚本可以立即访问 DOM 元素,无需等待。<script src="path/to/script.js"></script>
  • 外部文件: 推荐的做法是将 JavaScript 代码保存在单独的 .js 文件中,并使用 <script src="..."></script> 进行链接。这样可以提高代码组织性、利用浏览器缓存以及代码重用性。

放置策略会影响页面加载性能和脚本行为。

关键语法元素包括:

  • 字面量 (Literals): 固定值(例如,100、'Hello'、true)。
  • 变量 (Variables): 用于存储数据的命名容器(例如,let age = 30; const name = 'Alice';)。
  • 运算符 (Operators): 对值执行操作(例如,+、-、*、/、=、===、&&、||)。
  • 表达式 (Expressions): 值、变量和运算符的组合,可以计算为一个单一值(例如,x * 5)。
  • 关键字 (Keywords): 具有特殊含义的保留字(例如,let、const、var、function、if、for、return)。
  • 语句 (Statements): 要执行的指令,通常以分号 (;) 结束,尽管由于自动分号插入 (Automatic Semicolon Insertion, ASI) 的存在,分号通常是可选的。
  • 注释 (Comments): 被解释器忽略,用于解释代码(例如,// 单行注释,/* 多行注释 */)。
  • 区分大小写 (Case Sensitivity): JavaScript 对大小写敏感(myVariable 和 myvariable 是不同的)。
  • 现代特性: 箭头函数 (=>),模板字面量 (`string ${expr}`),解构赋值 (const {prop} = obj;),展开/剩余运算符 (...)。

语法细节将在后续章节中介绍。

JavaScript 程序由一系列语句组成。

  • 命令: 每个语句都是浏览器/引擎要执行的命令。
  • 分号: 语句通常以分号 (;) 分隔。虽然由于 ASI 的存在通常是可选的,但显式地使用分号是一种常见的良好实践,以避免歧义。
  • 空白符: JavaScript 忽略多个空格和换行符,允许灵活的代码格式化。
  • 代码块: 语句可以使用花括号 {...} 分组到代码块中,例如在函数或条件语句中。使用 let 和 const 声明的变量具有块级作用域 (block-scoped)。

理解语句是编写 JavaScript 的基础。

注释用于向代码添加解释性说明,使其更易于理解。它们会被 JavaScript 解释器忽略。

  • 单行注释: 以 // 开头。从 // 到行尾的所有内容都是注释。 // 这是一个单行注释
  • 多行注释: 以 /* 开头,以 */ 结束。可以跨多行。 /* 这是一个 多行注释 */
  • 用例: 解释复杂逻辑,临时禁用代码(注释掉)。

良好的注释使代码更易于维护。

变量是用于存储数据值的容器。

  • 声明 (Declaration): 使用 let 声明值可能改变的变量,使用 const 声明值不应被重新赋值的变量(常量)。var 是较旧的方式,具有函数作用域 (function-scope) 或全局作用域 (global-scope),并且存在提升 (hoisting) 的特性;在现代 JavaScript 中通常不鼓励使用它。 let age = 25; const name = "Alex";
  • 作用域 (Scope): let 和 const 是块级作用域 (block-scoped) 的(仅在定义它们的 {...} 块内可见)。var 是函数作用域或全局作用域的。
  • 赋值 (Assignment): 使用赋值运算符 = 为变量赋值。
  • 命名规则: 变量名可以包含字母、数字、下划线 (_) 和美元符号 ($)。它们必须以字母、$ 或 _ 开头。区分大小写。
  • undefined: 一个已声明但未赋值的变量,其值为 undefined。
  • 重复声明: 在同一作用域内重复声明 var 变量是允许的(但这通常不是好的实践)。在同一作用域内重复声明 let 或 const 变量会抛出错误。

默认情况下优先使用 const;仅在需要重新赋值时使用 let。

算术运算符执行数学计算:

  • + (加法):let sum = 5 + 3; // 8
  • - (减法):let difference = 5 - 3; // 2
  • * (乘法):let product = 5 * 3; // 15
  • / (除法):let quotient = 10 / 2; // 5
  • % (取模 - 除法的余数):let remainder = 10 % 3; // 1
  • ** (幂运算 - ES2016):let power = 2 ** 3; // 8 (2 的 3 次方)
  • ++ (自增):let count = 5; count++; // count 现在是 6 (可以是前置或后置自增)
  • -- (自减):let val = 5; val--; // val 现在是 4 (可以是前置或后置自减)

运算符优先级决定了运算的顺序(例如,乘法和除法 (* 和 /) 优先于加法和减法 (+ 和 -))。可以使用括号 () 来控制运算顺序。

赋值运算符用于将值赋给 JavaScript 变量。

  • = (赋值):let x = 10;
  • += (加法赋值):x += 5; // 等同于 x = x + 5;
  • -= (减法赋值):x -= 3; // 等同于 x = x - 3;
  • *= (乘法赋值):x *= 2; // 等同于 x = x * 2;
  • /= (除法赋值):x /= 4; // 等同于 x = x / 4;
  • %= (取模赋值):x %= 3; // 等同于 x = x % 3;
  • **= (幂运算赋值):x **= 2; // 等同于 x = x ** 2;

这些运算符提供了涉及赋值的常见操作的简写方式。

将字符串组合起来称为拼接 (concatenation)。

  • + 运算符: 最常用的方式。 let firstName = "John"; let lastName = "Doe"; let fullName = firstName + " " + lastName; // "John Doe"
  • += 运算符: 用于向现有字符串追加内容。 let message = "Hello"; message += " World!"; // "Hello World!"
  • 模板字面量 (Template Literals, ES6): 一种更现代、更灵活的方式,使用反引号 (`) 和 ${expression} 占位符。 let city = "New York"; let greeting = Welcome to ${city}!; // "Welcome to New York!" 模板字面量也方便支持多行字符串。

模板字面量因其可读性和强大功能而通常更受青睐。

JavaScript 有几种数据类型:

  • 基本类型 (Primitive Types):
    • String (字符串):文本数据(例如,'hello',"world")。
    • Number (数字):数值,包括整数和浮点数(例如,100,3.14)。也包括特殊值,如 NaN 和 Infinity。
    • Boolean (布尔值):逻辑值,true 或 false。
    • undefined (未定义):表示未初始化变量或缺失的值。
    • null (空值):表示故意没有对象值。它是一个赋值的值。
    • Symbol (符号,ES6):独一无二且不可变的原始值,常用于对象属性键。
    • BigInt (ES2020):用于表示 Number 类型无法安全表示的更大整数。
  • 对象类型 (Object Type,引用类型):
    • Object (对象):键值对(属性)的集合。包括数组、函数、日期等。 JavaScript 是动态类型 (dynamically typed) 的,这意味着你不需要声明变量的类型;变量的类型是在运行时 (runtime) 由赋给它的值决定的。

使用 typeof 运算符可以查找变量的类型(例如,typeof "hello" 返回 "string")。

对象是属性的集合,每个属性都是一个键值对。键通常是字符串(或 Symbol),值可以是任何数据类型,包括其他对象或函数(方法)。

  • 对象字面量语法 (Object Literal Syntax): 创建对象最常用的方式。 const person = { firstName: "Jane", lastName: "Doe", age: 30, greet: function() { console.log("Hello!"); }, // ES6 方法简写 sayHi() { console.log("Hi!"); } };
  • 访问属性:
    • 点表示法 (Dot notation):person.firstName
    • 方括号表示法 (Bracket notation):person["lastName"] (适用于动态属性名或包含特殊字符的名称)。
  • 修改属性: person.age = 31;
  • 添加属性: person.city = "London";
  • 删除属性: delete person.age;
  • ES6 增强: 属性简写 (Shorthand property names)(如果键名与变量名一致)、计算属性名 (computed property names)({[myVar]: value})、方法简写 (method shorthand)。

对象是 JavaScript 中数据结构化的基础。

函数是可重用的代码块,用于执行特定任务。它们可以接收输入(参数),并返回输出(一个值)。

  • 函数声明 (Function Declaration): function add(a, b) { return a + b; } let sum = add(5, 3); // 8
  • 函数表达式 (Function Expression): 将函数赋给变量。 const multiply = function(a, b) { return a * b; }; let product = multiply(4, 2); // 8
  • 箭头函数 (Arrow Functions, ES6): 编写函数的简洁语法。它们具有不同的 this 绑定行为。 const subtract = (a, b) => a - b; let difference = subtract(10, 3); // 7 const greet = name => Hello, ${name}!;
  • 参数 (Parameters) 和实参 (Arguments): 参数在函数定义中命名;实参是在调用函数时传递的实际值。
  • 默认参数 (Default Parameters, ES6): function greetUser(name = "Guest") { ... }
  • 剩余参数 (Rest Parameters, ES6): function sumAll(...numbers) { ... } (将剩余的实参收集到一个数组中)。
  • 返回值 (Return Value): 使用 return 关键字。如果省略,函数返回 undefined。

函数在 JavaScript 中是“头等公民”(first-class citizens),这意味着它们可以像任何其他值一样对待(作为实参传递,从其他函数返回,赋给变量)。

事件 (Events) 是在浏览器中发生的动作,例如用户点击按钮、页面完成加载或按下键盘按键。JavaScript 可以响应这些事件。

  • 事件处理程序 (Event Handlers): 事件发生时执行的函数。
  • addEventListener() 方法: 处理事件的推荐方式。它允许为一个事件绑定多个处理程序,并提供更多控制。 const myButton = document.getElementById("myBtn"); myButton.addEventListener("click", function() { console.log("Button clicked!"); });
  • 内联事件处理程序 (Inline Event Handlers,较旧,不推荐): <button onclick="myFunction()">Click Me</button>。更难维护,且将 HTML 与 JavaScript 逻辑混合。
  • 常见事件: click、mouseover、mouseout、keydown、keyup、submit (用于表单)、load (用于窗口或图像)。
  • 事件对象 (Event Object): 通常作为实参传递给事件处理函数,包含有关事件的信息(例如,event.target 指代触发事件的元素)。

事件处理是创建交互式网页的关键。

字符串是字符序列。JavaScript 提供了许多内置方法来处理字符串。

  • 创建字符串: 使用单引号 ('...')、双引号 ("...") 或模板字面量 (`...`)。
  • length 属性: "hello".length; // 5
  • 访问字符: "hello"[0]; // 'h' (字符串是基于 0 的索引)。
  • 常用方法:
    • indexOf(substring)、lastIndexOf(substring):查找子字符串的位置。
    • slice(start, end)、substring(start, end):提取字符串的一部分。
    • replace(old, new)、replaceAll(old, new):替换子字符串的出现位置。
    • toUpperCase()、toLowerCase():改变大小写。
    • trim()、trimStart()、trimEnd():移除空白符。
    • split(separator):将字符串转换为数组。
    • includes(substring)、startsWith(substring)、endsWith(substring):检查是否包含子字符串。
    • padStart(targetLength, padString)、padEnd(targetLength, padString):添加填充。
  • 不可变性 (Immutability): 字符串是不可变的。字符串方法返回新的字符串;它们不修改原始字符串。

模板字面量对于在字符串中嵌入表达式非常强大:`User: ${userName}`。

JavaScript 只有一种 Number 类型,用于表示整数和浮点数。

  • 字面量: 100、3.14159、1.2e6 (指数表示法)。
  • 特殊值:
    • Infinity (正无穷大)、-Infinity (负无穷大):表示超出可表示范围的值。
    • NaN (非数字,Not-a-Number):无效数学操作的结果(例如,0/0,parseInt("apple"))。
  • 浮点数精度 (Floating-Point Precision): 由于二进制表示,要注意浮点数运算可能存在精度问题(例如,0.1 + 0.2 !== 0.3)。对于精确计算(例如货币),考虑使用库或采用处理整数的策略。
  • Number 对象方法:
    • Number.parseInt(string, radix):将字符串转换为整数。
    • Number.parseFloat(string):将字符串转换为浮点数。
    • Number.isNaN(value):检查一个值是否是 NaN(比全局 isNaN() 更安全)。
    • Number.isFinite(value):检查一个值是否是有限数。
  • 实例方法(在数字值上):
    • num.toFixed(digits):将数字格式化为指定的小数位数,返回一个字符串。
    • num.toPrecision(precision):将数字格式化为指定的精度长度,返回一个字符串。
    • num.toString(radix):将数字转换为字符串,可选择指定基数(例如,2 表示二进制,16 表示十六进制)。

Math 对象提供了更高级的数学函数。

Math 对象是一个内置对象,包含用于数学常数和函数的属性和方法。它不是一个构造函数。

  • 常量:
    • Math.PI:圆周率的值(约 3.14159)。
    • Math.E:欧拉常数(约 2.718)。
  • 常用方法:
    • Math.round(x):四舍五入到最接近的整数。
    • Math.ceil(x):向上舍入到最接近的整数。
    • Math.floor(x):向下舍入到最接近的整数。
    • Math.trunc(x):返回 x 的整数部分(移除小数)。
    • Math.abs(x):返回绝对值(正值)。
    • Math.sqrt(x):返回平方根。
    • Math.pow(base, exponent):返回 base 的 exponent 次幂(等同于 base ** exponent)。
    • Math.min(n1, n2, ...)、Math.max(n1, n2, ...):返回一组数字中的最小值或最大值。
    • Math.random():返回介于 0(包含)和 1(不包含)之间的伪随机浮点数。要在一定范围内获取随机整数,可以结合 Math.floor() 和乘法使用。

示例:获取 1 到 10 之间的随机整数:Math.floor(Math.random() * 10) + 1。

Date 对象用于处理日期和时间。

  • 创建日期:
    • new Date():当前日期和时间。
    • new Date(milliseconds):从 1970 年 1 月 1 日协调世界时 (UTC)(Unix 纪元)开始的毫秒数。
    • new Date(dateString):例如,"2023-10-26","October 26, 2023 14:30:00"。
    • new Date(year, monthIndex, day, hours, minutes, seconds, milliseconds):monthIndex 是 0-11(0 表示一月,11 表示十二月)。
  • 获取日期/时间组件:
    • getFullYear() (获取年份)、getMonth() (获取月份,0-11)、getDate() (获取日期,1-31)。
    • getHours() (获取小时)、getMinutes() (获取分钟)、getSeconds() (获取秒)、getMilliseconds() (获取毫秒)。
    • getDay():星期几(0 表示周日,1 表示周一,…,6 表示周六)。
    • getTime():从 Unix 纪元开始的毫秒数。
  • 设置日期/时间组件:
    • setFullYear()、setMonth()、setDate() 等。
  • 格式化:
    • toDateString():人类可读的日期部分。
    • toTimeString():人类可读的时间部分。
    • toLocaleDateString()、toLocaleTimeString():本地化格式。
    • toISOString():ISO 8601 格式(例如,"2023-10-26T14:30:00.000Z")。 对于复杂的日期操作,可以考虑使用 date-fns 或 Day.js 等库,它们提供了更强大的解析、格式化和时区处理功能。

示例:const today = new Date(); console.log(today.toLocaleDateString());

数组是有序的值列表。值可以是任何数据类型。

  • 创建数组: 使用数组字面量:const fruits = ["Apple", "Banana", "Cherry"];
  • 访问元素: 基于 0 的索引:fruits[0]; // "Apple"。
  • length 属性: fruits.length; // 3。
  • 常见修改方法(会改变原始数组):
    • push(item):添加到末尾。pop():从末尾移除。
    • unshift(item):添加到开头。shift():从开头移除。
    • splice(startIndex, deleteCount, ...itemsToAdd):多功能方法,用于添加/移除/替换元素。
    • sort(compareFunction):对元素进行排序。默认按字符串转换后排序。
    • reverse():反转元素顺序。
  • 常见访问/迭代方法(返回新数组或值,不改变原始数组):
    • slice(start, end):返回数组一部分的浅拷贝 (shallow copy)。
    • concat(...arrays):合并数组。
    • join(separator):将数组转换为字符串。
    • indexOf(item)、lastIndexOf(item):查找元素的索引。
    • includes(item):检查是否存在某个元素。
    • 迭代方法 (Iteration Methods, ES5+):
      • forEach(callback):对数组中的每个元素执行一个函数。
      • map(callback):通过转换每个元素来创建一个新数组。
      • filter(callback):创建一个新数组,其中包含通过指定测试的元素。
      • reduce(callback, initialValue):将数组归约 (reduces) 为一个单一值。
      • find(callback):返回第一个通过测试的元素。
      • findIndex(callback):返回第一个通过测试的元素的索引。
      • some(callback)、every(callback):测试是否部分/所有元素通过测试。
  • 展开运算符 (Spread Operator, ...) (ES6): 用于复制 ([...oldArray])、合并以及将元素作为实参传递。
  • 解构赋值 (Destructuring Assignment, ES6): const [first, second] = fruits;

数组是 JavaScript 中数据操作的基石。

当运算符与不同类型的值一起使用时,JavaScript 经常执行自动类型转换(称为强制转换,coercion)。理解这一点很重要,但显式转换通常更清晰。

  • 显式转换 (Explicit Conversion):
    • 转为 String (字符串): String(123) 或 123.toString()。
    • 转为 Number (数字): Number("456")、parseInt("100px") (解析直到遇到非数字字符)、parseFloat("3.14em")。 一元加号运算符 (+) 也可以将值转换为数字:+"789"。
    • 转为 Boolean (布尔值): Boolean(value)。假值 (Falsy values)(false、0、""、null、undefined、NaN)转换为 false;所有其他值(真值 Truthy values)转换为 true。
  • 隐式转换 (Implicit Coercion) 示例:
    • "5" + 3 的结果是 "53"(数字被转换为字符串进行拼接)。
    • "10" - 5 的结果是 5(字符串被转换为数字进行减法)。
    • if (value) {...}:value 被隐式转换为布尔值。
  • 检查类型: typeof value。
  • 检查是否为数组: Array.isArray(value)。
  • 检查是否为 Date 对象: value instanceof Date。

理解强制转换有助于调试意外的行为。比较时优先使用严格相等 (===),以避免不想要的类型强制转换带来的潜在问题。

布尔值代表逻辑值:true 或 false。

  • 布尔字面量: true,false。
  • 比较产生布尔值: 5 > 3; // true
  • 真值 (Truthy) 和假值 (Falsy): 在需要布尔值的上下文(例如 if 条件)中,JavaScript 会将其他类型强制转换为布尔值。
    • 假值 (Falsy Values): 这些值会转换为 false:
      • false
      • 0 (以及 -0)
      • "" (空字符串)
      • null
      • undefined
      • NaN (非数字,Not-a-Number)
    • 真值 (Truthy Values): 所有其他值都是真值,包括:
      • 非空字符串(例如,"hello","0","false")
      • 非零数字(例如,1,-1)
      • 对象(包括空对象 {} 和空数组 [])
      • 函数
  • Boolean() 函数: 显式地将一个值转换为布尔值:Boolean("text"); // true,Boolean(0); // false。

理解真值/假值对于条件逻辑至关重要。

比较运算符用于比较两个值,并返回布尔值(true 或 false)。

  • 相等性:
    • == (宽松/抽象相等 Loose/Abstract Equality):如果在比较时类型不同,会进行类型强制转换后再比较值。由于行为不可预测,通常不建议使用。 5 == "5"; // true
    • === (严格相等 Strict Equality):不进行类型强制转换,直接比较值和类型。如果类型不同,返回 false。在大多数比较中优先使用。 5 === "5"; // false 5 === 5; // true
  • 不等性:
    • != (宽松不等 Loose Inequality):5 != "5"; // false
    • !== (严格不等 Strict Inequality):5 !== "5"; // true 优先使用。
  • 关系运算符 (Relational Operators):
    • > (大于):10 > 5; // true
    • < (小于):10 < 5; // false
    • >= (大于或等于):10 >= 10; // true
    • <= (小于或等于):5 <= 10; // true 比较对象(包括数组和函数)时,相等运算符 (==、===) 检查它们是否引用内存中的同一个对象,而不是内容是否相同。

始终优先使用严格比较 (===、!==),以避免因类型强制转换引起的细微错误。

条件语句根据条件执行不同的代码块。

  • if 语句: 如果条件为 true 则执行代码。 if (age >= 18) { console.log("Adult"); }
  • if...else 语句: 如果条件为 true 则执行一个代码块,如果为 false 则执行另一个。 if (score >= 50) { console.log("Pass"); } else { console.log("Fail"); }
  • if...else if...else 语句: 用于处理多个条件。 if (grade >= 90) { console.log("A"); } else if (grade >= 80) { console.log("B"); } else { console.log("C or below"); }
  • switch 语句: 选择多个代码块中的一个执行。适用于处理多个离散值。 switch (dayOfWeek) { case "Monday": console.log("Start of week"); break; case "Friday": console.log("Almost weekend!"); break; default: console.log("Another day"); } (需要 break 语句来防止代码“贯穿”执行)。
  • 三元运算符 (Ternary Operator, condition ? exprIfTrue : exprIfFalse): 编写简单 if-else 语句的简洁方式。 let type = age >= 18 ? "Adult" : "Minor";

条件语句是控制程序流程的基础。

循环会重复执行一个代码块多次。

  • for 循环: 当你知道要重复执行的次数时使用。 for (let i = 0; i < 5; i++) { console.log(i); } // 0, 1, 2, 3, 4
  • while 循环: 只要条件为 true 就重复执行。条件在每次迭代前检查。 let count = 0; while (count < 3) { console.log(count); count++; } // 0, 1, 2
  • do...while 循环: 类似于 while,但代码块至少执行一次,之后才检查条件。 let num = 0; do { console.log(num); num++; } while (num < 0); // 0
  • for...in 循环: 迭代对象的可枚举属性(通常是键)。 const person = { name: "Alice", age: 30 }; for (const key in person) { console.log(${key}: ${person[key]}); }
  • for...of 循环 (ES6): 迭代可迭代对象(如 Array、String、Map、Set)的值。 const colors = ["red", "green", "blue"]; for (const color of colors) { console.log(color); }
  • break 语句: 提前退出循环。
  • continue 语句: 跳过当前迭代,继续下一次迭代。

选择最适合迭代逻辑的循环类型。for...of 通常用于迭代数组的值。

JavaScript 错误处理(try...catch...finally)

Section titled “JavaScript 错误处理(try...catch...finally)”

错误处理允许你优雅地管理运行时错误。

  • try 块: 包含可能抛出错误的代码。

  • catch 块: 如果 try 块中发生错误则执行。它接收一个错误对象,其中包含详细信息(例如,error.message、error.name)。

  • finally 块: 在 try(以及 catch,如果发生错误)之后执行,无论是否抛出错误。对于清理任务(例如,关闭资源)很有用。

  • throw 语句: 创建自定义错误。throw new Error("Something went wrong!"); 或 throw "Custom error message";

    try { let result = riskyOperation(); console.log(result); } catch (error) { console.error("发生了一个错误:", error.message); } finally { console.log("操作完成,如果需要进行清理。"); }

  • 错误对象 (Error Objects): 内置错误类型包括 Error、SyntaxError、ReferenceError、TypeError 等。你可以通过继承 Error 创建自定义错误类。

适当的错误处理使应用程序更健壮。

正则表达式是用于在字符串中匹配字符组合的模式。它们对于文本搜索、验证和操作非常强大。

  • 创建 RegExp 对象:
    • 字面量方式:const pattern = /abc/i;(i 是一个标志 (flag),表示不区分大小写)。
    • 构造函数方式:const pattern = new RegExp("abc", "i");
  • 常见 RegExp 方法(在 String 对象上):
    • string.match(pattern):返回匹配结果数组或 null。
    • string.search(pattern):返回第一个匹配项的索引,如果没有匹配到则返回 -1。
    • string.replace(pattern, replacement):将匹配项替换为字符串或函数的结果。
    • string.split(pattern):根据匹配项分割字符串。
  • RegExp 方法(在 RegExp 对象上):
    • pattern.test(string):如果存在匹配项,返回 true,否则返回 false。
    • pattern.exec(string):返回匹配详情的数组或 null;对于全局搜索会推进位置。
  • 常见模式语法:
    • . (除换行符外的任意字符)、\d (数字字符)、\w (单词字符)、\s (空白字符)。
    • * (0 次或多次)、+ (1 次或多次)、? (0 次或 1 次)。
    • [] (字符集)、() (捕获组)、| (或)。
    • ^ (字符串/行的开头)、$ (字符串/行的结尾)。
  • 标志 (Flags): g (全局匹配)、i (不区分大小写)、m (多行匹配)。

示例:验证邮箱格式(简化版): const emailPattern = /^\S+@\S+\.\S+$/; console.log(emailPattern.test("test@example.com")); // true

对象在 JavaScript 中是基础概念,作为键值对的集合。

  • 对象字面量: const car = { make: "Toyota", model: "Camry" };
  • 构造函数 (Constructors): 使用 new 关键字调用构造函数(例如,new Date(),或自定义构造函数)。 function Person(name, age) { this.name = name; this.age = age; } const person1 = new Person("Bob", 40);
  • 原型 (Prototypes) 和继承 (Inheritance): 对象从其原型继承属性和方法。这构成了 JavaScript 原型继承的基础。
  • this 关键字: 它的值取决于函数的调用方式(例如,在对象方法中,this 指代该对象;在箭头函数中,this 是词法绑定 (lexically bound) 的)。
  • ES6+ 特性:
    • 类语法 (Class syntax):原型继承之上的语法糖 (Syntactic sugar)(class Car { constructor(...) { ... } drive() { ... } })。
    • 模块 (Modules):用于将代码组织成可重用部分(import/export)。
    • Getter (取值器) 和 Setter (设置器):get propertyName() { ... },set propertyName(value) { ... }。
    • Object.keys(obj)、Object.values(obj)、Object.entries(obj):获取键数组、值数组或 [键, 值] 对的数组。
    • Object.assign(target, ...sources):将属性从源对象复制到目标对象。
    • 对象的展开语法 (...):用于克隆或合并对象(const newObj = { ...oldObj, newProp: val };)。

对象是可变的 (mutable)(创建后其属性可以更改),这与基本类型不同。

属性是构成对象的键值对。

  • 访问:
    • 点表示法:object.propertyName
    • 方括号表示法:object["propertyName"] 或 object[variableContainingPropertyName]
  • 添加/修改: object.newProperty = "value"; 或 object.existingProperty = "newValue";
  • 删除: delete object.propertyName; (从对象中移除该属性)。
  • 枚举属性 (Enumerating Properties):
    • for...in 循环:迭代可枚举的、自身和继承的属性(使用 obj.hasOwnProperty(key) 检查是否为自身属性)。
    • Object.keys(obj):返回自身可枚举属性名的数组。
    • Object.getOwnPropertyNames(obj):返回所有自身属性名(无论是否可枚举)的数组。
  • 属性描述符 (Property Descriptors): 属性具有内部属性(描述符),如 value、writable、enumerable、configurable。这些可以使用 Object.defineProperty() 和 Object.defineProperties() 进行控制。
  • 属性简写 (Shorthand Properties, ES6): 如果变量名与期望的属性键相同:const name = "Alice"; const person = { name, age: 30 }; // person.name is "Alice"
  • 计算属性名 (Computed Property Names, ES6): 使用方括号中的表达式作为键:const propName = "dynamicKey"; const obj = { [propName]: "some value" };

理解如何处理对象属性对于高效的 JavaScript 编程至关重要。