JavaScript 教程 [最新版]:新手起步 – wiki基地


JavaScript 教程 [最新版]:新手起步 – 从零到一的编程之旅

欢迎来到 JavaScript 的世界!无论你是完全的编程新手,还是希望扩展技能栈的开发者,这份详尽的 JavaScript 入门教程都将为你打下坚实的基础。JavaScript 是当今互联网的基石之一,驱动着绝大多数现代网站的交互性和动态功能。掌握它,你将能够为网页添加活力,构建复杂的 Web 应用程序,甚至涉足服务器端开发(Node.js)、移动应用(React Native, NativeScript)等领域。

本教程面向绝对零基础的初学者,我们将从最基本的概念讲起,逐步深入,力求让你不仅“知其然”,更能“知其其所以然”。

教程目标:

  • 理解 JavaScript 是什么,以及它在 Web 开发中的作用。
  • 掌握 JavaScript 的基本语法、数据类型和核心结构。
  • 学会如何在网页中引入和运行 JavaScript 代码。
  • 能够编写简单的脚本来操作网页内容(DOM 基础)。
  • 为后续深入学习打下坚实基础。

准备工作:

你只需要两样东西:

  1. 一个现代的网页浏览器: Chrome、Firefox、Edge 或 Safari 都可以。它们都内置了强大的开发者工具,是学习和调试 JavaScript 的利器。
  2. 一个文本编辑器: 你可以用系统自带的记事本(Windows)或文本编辑(Mac),但强烈推荐使用更专业的代码编辑器,如 VS Code (Visual Studio Code,免费且功能强大)、Sublime Text 或 Atom。这些编辑器提供语法高亮、代码提示等功能,能极大提升你的学习和开发效率。

第一章:JavaScript 简介 – 开启你的编程之门

1.1 什么是 JavaScript?

JavaScript (简称 JS) 是一种轻量级、解释型、面向对象的脚本语言。听起来很复杂?别担心,我们来分解一下:

  • 脚本语言 (Scripting Language): 意味着它通常不需要像 C++ 或 Java 那样先编译成机器码再运行。浏览器(或 Node.js 环境)会直接读取你的 JS 代码,并一行行地解释执行。这使得开发周期更快,更容易上手。
  • 轻量级 (Lightweight): 相对于一些大型编程语言,JS 的核心功能集相对较小,但通过其强大的生态系统(库和框架)可以实现极其复杂的功能。
  • 解释型 (Interpreted): 代码在运行时由解释器(浏览器中的 JS 引擎,如 V8、SpiderMonkey)逐行翻译执行。
  • 面向对象 (Object-Oriented): 虽然 JS 的面向对象模型与其他语言(如 Java)有所不同(基于原型),但它确实支持封装、继承(通过原型链)和多态等面向对象的概念,允许你用对象来组织代码。

最重要的是: JavaScript 是唯一一种能够直接在网页浏览器中运行的编程语言。它赋予了网页动态交互的能力。

1.2 JavaScript 能做什么?

想象一下没有 JavaScript 的网页:它就像一张静态的海报,内容固定,无法响应你的操作。有了 JavaScript,网页就能:

  • 响应用户操作: 点击按钮、鼠标悬停、键盘输入等,都可以触发 JS 代码执行相应的功能(如弹出菜单、验证表单、发送数据)。
  • 修改网页内容: 动态地添加、删除或修改 HTML 元素和文本内容,无需刷新整个页面(想想无限滚动的社交媒体信息流)。
  • 改变网页样式: 动态地修改 CSS 样式,实现动画效果、主题切换等。
  • 与用户交互: 创建弹出窗口、提示框、确认框等。
  • 与服务器通信: 在后台发送和接收数据(AJAX/Fetch API),实现无需页面刷新的数据更新(如在线聊天、实时股价)。
  • 执行复杂的计算和逻辑: 在浏览器端处理数据、进行游戏逻辑运算等。

超越浏览器:

  • Node.js: 让 JavaScript 能够运行在服务器端,用于构建后端服务、API 等。
  • 移动应用: 框架如 React Native, NativeScript 允许使用 JavaScript 构建原生移动应用。
  • 桌面应用: 框架如 Electron 允许使用 Web 技术(包括 JS)构建跨平台桌面应用(如 VS Code 本身就是用 Electron 构建的)。

1.3 JavaScript 不是 Java!

这是一个常见的误区。JavaScript 和 Java 是两种完全不同的编程语言,尽管名字相似。它们由不同的公司开发,语法、设计哲学和应用领域都有很大差异。记住这一点!


第二章:初识 JavaScript – 环境搭建与第一个程序

2.1 JavaScript 的运行环境

最常见的运行环境就是你的网页浏览器。每个现代浏览器都内置了一个 JavaScript 引擎:

  • Chrome: V8 引擎
  • Firefox: SpiderMonkey 引擎
  • Safari: JavaScriptCore 引擎
  • Edge: (基于 Chromium) V8 引擎

此外,Node.js 提供了一个可以在服务器或本地计算机上运行 JavaScript 的环境。在本入门教程中,我们主要关注浏览器环境。

2.2 如何在 HTML 中引入 JavaScript

有三种主要方式将 JavaScript 代码添加到 HTML 页面中:

  1. 内部脚本 (Internal Script): 使用 <script> 标签将代码直接嵌入 HTML 文件中。通常放在 <head><body> 标签的末尾。

    “`html
    <!DOCTYPE html>


    我的第一个 JS 页面

    欢迎!

    <script>
        // 这是 JavaScript 代码
        console.log("你好,JavaScript!来自内部脚本");
        alert("这是一个弹窗!"); // alert 会弹出一个提示框
    </script>
    



    “`

  2. 外部脚本 (External Script): 这是推荐的方式。将 JavaScript 代码保存在一个单独的 .js 文件中,然后通过 <script> 标签的 src 属性链接到 HTML 文件。这使得代码更易于维护、重用和缓存。

    • 创建一个 main.js 文件 (与 HTML 文件放在同一目录下或指定路径):

      javascript
      // main.js
      console.log("你好,JavaScript!来自外部文件");
      alert("来自外部文件的弹窗!");

    • 在 HTML 文件中引用它:

      “`html
      <!DOCTYPE html>


      使用外部 JS 文件

      查看控制台和弹窗

      <!-- 推荐将 script 标签放在 body 结束标签之前 -->
      <!-- 这样可以确保 HTML 元素加载完毕后再执行 JS -->
      <script src="main.js"></script>
      



      “`

  3. 内联脚本 (Inline Script – 不推荐): 直接将少量 JS 代码写在 HTML 元素的事件属性中(如 onclick)。这种方式难以维护,应尽量避免。

    html
    <button onclick="alert('按钮被点击了!');">点我</button>

最佳实践: 始终优先使用外部脚本,并将 <script> 标签放在 </body> 之前。这可以确保 HTML 结构完全加载解析完毕后,JS 代码再去操作它们,避免因元素未加载而导致的错误,同时也能提高页面的初始渲染速度。

2.3 “Hello, World!” – 你的第一个 JavaScript 程序

让我们通过最经典的 “Hello, World!” 来正式开始。我们将使用 console.log(),这是一个非常有用的函数,可以将信息输出到浏览器的开发者控制台。

  1. 创建 HTML 文件 (index.html):

    “`html
    <!DOCTYPE html>




    Hello World

    打开开发者控制台查看消息

    <script src="app.js"></script>
    



    “`

  2. 创建 JavaScript 文件 (app.js):

    javascript
    // app.js
    console.log("Hello, World!");
    console.log("你好,世界!");

  3. 运行:

    • 用浏览器打开 index.html 文件。
    • 页面上会显示 “打开开发者控制台查看消息”。
    • 打开开发者控制台: 在页面上右键 -> 选择 “检查” (Inspect) 或 “检查元素” (Inspect Element),然后切换到 “控制台” (Console) 标签页。
    • 你将在控制台中看到输出的两行文字:”Hello, World!” 和 “你好,世界!”。

console.log() 是你最好的朋友! 在学习和调试过程中,你会频繁使用 console.log() 来检查变量的值、代码的执行流程等。


第三章:JavaScript 基础语法 – 构建代码的砖瓦

3.1 注释 (Comments)

注释是代码中不会被执行的部分,用于解释代码的功能、目的或留下笔记。良好的注释习惯非常重要。

“`javascript
// 这是一个单行注释

/
这是一个
多行注释。
可以跨越多行。
/

let message = “Hello”; // 也可以在代码行后面添加注释
“`

3.2 语句 (Statements)

JavaScript 代码由一系列语句组成,每个语句执行一个特定的任务。语句通常以分号 (;) 结尾。虽然在很多情况下 JavaScript 会自动插入分号(ASI – Automatic Semicolon Insertion),但强烈建议始终手动添加分号,以避免潜在的歧义和错误。

javascript
let name = "Alice"; // 这是一个赋值语句
console.log(name); // 这是一个函数调用语句
let age = 30; // 另一个赋值语句

3.3 变量 (Variables)

变量是用来存储数据的容器。在使用变量之前,需要先声明它。在现代 JavaScript (ES6 及以后版本) 中,我们主要使用 letconst 来声明变量。

  • let: 声明一个可以被重新赋值的变量。

    “`javascript
    let score = 0;
    console.log(score); // 输出: 0

    score = 100; // 可以重新赋值
    console.log(score); // 输出: 100

    let userName; // 可以只声明,不立即赋值,此时它的值是 undefined
    console.log(userName); // 输出: undefined
    userName = “Bob”;
    console.log(userName); // 输出: Bob
    “`

  • const: 声明一个常量,其值在声明时必须初始化,并且不能被重新赋值。这有助于代码的健壮性,表示这个值不应该改变。

    “`javascript
    const PI = 3.14159;
    console.log(PI); // 输出: 3.14159

    // PI = 3.14; // 这会抛出一个错误 (TypeError: Assignment to constant variable.)

    // const MAX_USERS; // 错误!常量必须在声明时初始化
    “`

    注意: 对于用 const 声明的对象或数组,虽然不能重新赋值整个变量,但可以修改对象内部的属性或数组的元素。

    “`javascript
    const user = { name: “Charlie”, age: 25 };
    user.age = 26; // 这是允许的,我们修改的是对象的属性,不是 user 变量本身
    console.log(user); // 输出: { name: ‘Charlie’, age: 26 }

    // user = { name: “David” }; // 错误!不能给常量重新赋值

    const colors = [“red”, “green”];
    colors.push(“blue”); // 这是允许的,我们修改的是数组的内容
    console.log(colors); // 输出: [‘red’, ‘green’, ‘blue’]

    // colors = [“yellow”]; // 错误!不能给常量重新赋值
    “`

  • var (旧方式 – 避免使用): 在 ES6 之前,var 是声明变量的唯一方式。它有一些作用域(后面会讲)和提升 (hoisting) 方面的问题,容易导致意想不到的行为。在现代 JavaScript 开发中,应优先使用 letconst,避免使用 var

变量命名规则:

  • 可以包含字母、数字、下划线 (_) 和美元符号 ($)。
  • 必须以字母、下划线或美元符号开头,不能以数字开头。
  • 区分大小写 (myVariablemyvariable 是不同的变量)。
  • 不能使用 JavaScript 的保留关键字(如 let, const, if, for, function 等)作为变量名。
  • 推荐使用驼峰命名法 (camelCase): 第一个单词小写,后续单词首字母大写,如 firstName, totalAmount, isUserLoggedIn

3.4 数据类型 (Data Types)

JavaScript 是一种动态类型语言,这意味着你不需要在声明变量时指定它的数据类型,变量的类型会在运行时根据赋给它的值自动确定。

JavaScript 主要有以下几种基本(原始)数据类型和一种复杂数据类型:

基本(原始)数据类型 (Primitive Types):

  1. string (字符串): 用于表示文本。用单引号 (') 或双引号 (") 包裹。

    `javascript
    let greeting = "Hello, world!";
    let name = 'Alice';
    let message = `你好,${name}!`; // ES6 模板字符串 (Template Literals),使用反引号 (`
    `),可以方便地嵌入变量

    console.log(greeting);
    console.log(message); // 输出: 你好,Alice!
    “`

  2. number (数字): 用于表示整数或浮点数(小数)。包括特殊值 Infinity (无穷大), -Infinity (负无穷大) 和 NaN (Not-a-Number,表示一个无法表示的数值结果,如 0 / 0)。

    “`javascript
    let age = 30;
    let price = 99.99;
    let temperature = -10;
    let result = 0 / 0; // NaN
    let infinity = Infinity;

    console.log(typeof age); // 输出: “number”
    console.log(typeof price); // 输出: “number”
    console.log(result); // 输出: NaN
    console.log(typeof NaN); // 输出: “number” (注意 NaN 本身是 number 类型)
    “`

  3. boolean (布尔值): 只有两个值:true (真) 和 false (假)。常用于逻辑判断。

    “`javascript
    let isLoggedIn = true;
    let hasPermission = false;

    console.log(typeof isLoggedIn); // 输出: “boolean”
    “`

  4. null: 表示一个有意设置的“空值”或“无对象”。它是一个表示“没有值”的值。

    javascript
    let selectedUser = null; // 表示当前没有选中用户
    console.log(selectedUser); // 输出: null
    console.log(typeof null); // 输出: "object" (这是一个历史遗留的 bug,但已被广泛接受)

  5. undefined: 表示一个变量已被声明,但尚未被赋值。或者访问对象上不存在的属性时也会得到 undefined

    javascript
    let address;
    console.log(address); // 输出: undefined
    console.log(typeof address); // 输出: "undefined"

  6. symbol (ES6新增): 表示唯一的、不可变的值。通常用作对象属性的键,以避免命名冲突。初学阶段可以暂时不用深入了解。

  7. bigint (ES2020新增): 用于表示超出 number 类型安全整数范围的极大整数。通过在整数末尾添加 n 来创建。初学阶段可以暂时不用深入了解。

    javascript
    const veryLargeNumber = 9007199254740991n; // 注意末尾的 'n'
    console.log(typeof veryLargeNumber); // 输出: "bigint"

复杂数据类型 (Complex Type):

  1. object (对象): 用于存储键值对的集合。是 JavaScript 中最重要的数据结构之一。可以包含各种数据类型(包括其他对象或函数)。

    “`javascript
    let person = {
    firstName: “John”, // firstName 是键 (key),”John” 是值 (value)
    lastName: “Doe”,
    age: 30,
    isStudent: false,
    address: { // 值可以是另一个对象
    street: “123 Main St”,
    city: “Anytown”
    },
    greet: function() { // 值可以是一个函数(称为方法)
    console.log(“Hello!”);
    }
    };

    console.log(person.firstName); // 访问属性:使用点 . 表示法
    console.log(person[“lastName”]); // 访问属性:也可以使用方括号 [] 表示法(键需要是字符串)
    console.log(person.address.city); // 访问嵌套对象的属性
    person.greet(); // 调用对象的方法

    console.log(typeof person); // 输出: “object”
    “`

    数组 (Array) 在 JavaScript 中也是一种特殊的对象。

typeof 操作符:

可以使用 typeof 操作符来检查一个变量的数据类型。

javascript
console.log(typeof "Hello"); // "string"
console.log(typeof 100); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (特殊情况)
console.log(typeof {}); // "object"
console.log(typeof []); // "object" (数组也是对象)
console.log(typeof function(){}); // "function" (函数有自己的 typeof 结果)


第四章:运算符与表达式 – 让代码动起来

运算符用于对值(操作数)执行操作。

4.1 算术运算符 (Arithmetic Operators)

用于执行数学计算。

  • + : 加法 (也可用于字符串连接)
  • - : 减法
  • * : 乘法
  • / : 除法
  • % : 取模 (求余数)
  • ** : 幂运算 (ES7)
  • ++ : 自增 (加 1)
  • -- : 自减 (减 1)

“`javascript
let a = 10;
let b = 3;

console.log(a + b); // 13
console.log(a – b); // 7
console.log(a * b); // 30
console.log(a / b); // 3.333…
console.log(a % b); // 1 (10 除以 3 余 1)
console.log(a ** b); // 1000 (10 的 3 次方)

let count = 5;
count++; // count 现在是 6 (后自增)
++count; // count 现在是 7 (前自增)
console.log(count); // 7

let str1 = “Hello”;
let str2 = ” World”;
console.log(str1 + str2); // “Hello World” (字符串连接)
console.log(“Score: ” + 100); // “Score: 100” (数字会转换为字符串再连接)
“`

注意 + 的特殊性: 如果 + 的操作数中有一个是字符串,它会执行字符串连接,而不是数学加法。如果想确保进行数学运算,可以使用 parseInt()parseFloat()Number() 将字符串转换为数字。

4.2 赋值运算符 (Assignment Operators)

用于给变量赋值。

  • = : 简单赋值
  • += : 加法赋值 (x += y 等同于 x = x + y)
  • -= : 减法赋值
  • *= : 乘法赋值
  • /= : 除法赋值
  • %= : 取模赋值
  • **= : 幂赋值

“`javascript
let x = 10;
let y = 5;

x += y; // x = x + y => x = 15
console.log(x); // 15

x *= 2; // x = x * 2 => x = 30
console.log(x); // 30
“`

4.3 比较运算符 (Comparison Operators)

用于比较两个值,返回一个布尔值 (truefalse)。

  • == : 等于 (值相等,会进行类型转换) – 不推荐
  • === : 严格等于 (值和类型都相等) – 推荐
  • != : 不等于 (值不相等,会进行类型转换) – 不推荐
  • !== : 严格不等于 (值或类型不相等) – 推荐
  • > : 大于
  • < : 小于
  • >= : 大于等于
  • <= : 小于等于

“`javascript
let num1 = 10;
let num2 = “10”;
let num3 = 20;

console.log(num1 == num2); // true (值相等,”10″ 被转换为 10)
console.log(num1 === num2); // false (类型不同,number vs string) – 推荐用这个!

console.log(num1 != num2); // false
console.log(num1 !== num2); // true – 推荐用这个!

console.log(num1 < num3); // true
console.log(num1 >= 10); // true
“`

重要: 始终优先使用严格等于 ===严格不等于 !== 来进行比较,这可以避免因隐式类型转换带来的潜在问题,让代码更可预测。

4.4 逻辑运算符 (Logical Operators)

用于组合多个布尔表达式。

  • && : 逻辑与 (AND) – 左右两边都为 true 时,结果才为 true
  • || : 逻辑或 (OR) – 左右两边只要有一个为 true 时,结果就为 true
  • ! : 逻辑非 (NOT) – 将 true 变为 falsefalse 变为 true

“`javascript
let isAdult = true;
let hasLicense = false;

console.log(isAdult && hasLicense); // false (必须都为 true)
console.log(isAdult || hasLicense); // true (只要有一个为 true)
console.log(!isAdult); // false (取反)
console.log(!hasLicense); // true (取反)

// 短路求值 (Short-circuiting):
// &&: 如果左边为 false,则不再计算右边
// ||: 如果左边为 true,则不再计算右边
let result1 = false && (console.log(“这不会执行”));
let result2 = true || (console.log(“这也不会执行”));
“`

4.5 三元运算符 (Ternary Operator)

if...else 语句的简洁形式。

语法:condition ? value_if_true : value_if_false

“`javascript
let age = 20;
let status = (age >= 18) ? “成年人” : “未成年人”;
console.log(status); // 输出: 成年人

let score = 75;
let grade = (score >= 90) ? “A” : (score >= 60) ? “B” : “C”;
console.log(grade); // 输出: B
“`


第五章:控制流程 – 决定代码的执行路径

控制流程语句用于根据条件或重复执行某段代码。

5.1 条件语句 (Conditional Statements)

  1. if 语句: 如果条件为 true,则执行代码块。

    javascript
    let temperature = 25;
    if (temperature > 30) {
    console.log("天气炎热!");
    }

  2. if...else 语句: 如果条件为 true,执行 if 块;否则,执行 else 块。

    javascript
    let hour = 14;
    if (hour < 12) {
    console.log("上午好!");
    } else {
    console.log("下午或晚上好!");
    }

  3. if...else if...else 语句: 检查多个条件。

    javascript
    let grade = 85;
    if (grade >= 90) {
    console.log("优秀 (A)");
    } else if (grade >= 80) {
    console.log("良好 (B)"); // 这个会执行
    } else if (grade >= 60) {
    console.log("及格 (C)");
    } else {
    console.log("不及格 (D)");
    }

  4. switch 语句: 基于一个表达式的值,执行多个可能匹配的代码块。通常用于替代多个 if...else if 判断同一个变量的情况。

    “`javascript
    let day = new Date().getDay(); // 获取今天是星期几 (0=周日, 1=周一, …)
    let dayName;

    switch (day) {
    case 0:
    dayName = “星期日”;
    break; // break 语句用于跳出 switch,否则会继续执行下一个 case
    case 1:
    dayName = “星期一”;
    break;
    case 2:
    dayName = “星期二”;
    break;
    case 3:
    dayName = “星期三”;
    break;
    case 4:
    dayName = “星期四”;
    break;
    case 5:
    dayName = “星期五”;
    break;
    case 6:
    dayName = “星期六”;
    break;
    default: // 如果没有任何 case 匹配,则执行 default
    dayName = “未知”;
    }
    console.log(今天是${dayName});
    “`

    注意 break 的重要性! 如果省略 break,代码会从匹配的 case 开始,一直执行下去,直到遇到 breakswitch 结束,这通常不是我们想要的结果(称为“穿透” fall-through)。

5.2 循环语句 (Looping Statements)

用于重复执行一段代码。

  1. for 循环: 最常用的循环,适用于已知循环次数的情况。
    语法:for (初始化; 条件; 迭代表达式)

    javascript
    // 打印 0 到 4
    for (let i = 0; i < 5; i++) {
    // i = 0, 条件 0 < 5 为 true, 执行代码块, i++ (i 变为 1)
    // i = 1, 条件 1 < 5 为 true, 执行代码块, i++ (i 变为 2)
    // ...
    // i = 4, 条件 4 < 5 为 true, 执行代码块, i++ (i 变为 5)
    // i = 5, 条件 5 < 5 为 false, 循环结束
    console.log("当前数字是: " + i);
    }

  2. while 循环: 当条件为 true 时,持续执行代码块。适用于不知道具体循环次数,但知道循环结束条件的情况。

    javascript
    let count = 0;
    while (count < 3) {
    console.log("While 循环计数: " + count);
    count++; // 必须在循环体内改变条件变量,否则可能导致死循环!
    }

  3. do...while 循环:while 类似,但它至少会执行一次代码块,然后再检查条件。

    javascript
    let num = 5;
    do {
    console.log("Do...while 执行了一次,num 是: " + num);
    num++;
    } while (num < 5); // 即使条件初始为 false (5 < 5 是 false),代码块也执行了一次

  4. for...in 循环 (用于遍历对象属性):

    javascript
    const user = { name: "Eve", age: 28, city: "London" };
    for (let key in user) {
    // key 是对象的属性名 (字符串)
    console.log(`${key}: ${user[key]}`); // 注意这里用方括号访问属性
    }
    // 输出:
    // name: Eve
    // age: 28
    // city: London

  5. for...of 循环 (ES6 – 用于遍历可迭代对象,如数组、字符串): 这是遍历数组等更常用的方式。

    “`javascript
    const colors = [“red”, “green”, “blue”];
    for (let color of colors) {
    // color 是数组中的每个元素值
    console.log(color);
    }
    // 输出:
    // red
    // green
    // blue

    const text = “Hello”;
    for (let char of text) {
    // char 是字符串中的每个字符
    console.log(char);
    }
    // 输出:
    // H
    // e
    // l
    // l
    // o
    “`

breakcontinue:

  • break: 完全跳出当前循环。
  • continue: 跳过当前这次循环的剩余代码,直接进入下一次迭代。

javascript
for (let i = 0; i < 10; i++) {
if (i === 3) {
continue; // 当 i 等于 3 时,跳过 console.log(i),进入下一次循环 (i 变成 4)
}
if (i === 7) {
break; // 当 i 等于 7 时,完全跳出 for 循环
}
console.log("循环数字: " + i); // 会打印 0, 1, 2, 4, 5, 6
}


第六章:函数 – 代码的复用与组织

函数是一段可以被重复调用(执行)的代码块。它们是组织和构建复杂程序的基本单元。

6.1 函数声明 (Function Declaration)

``javascript
// 定义一个名为 greet 的函数
function greet(name) { // name 是参数 (parameter)
console.log(
你好, ${name}!`);
}

// 调用函数
greet(“张三”); // “张三” 是参数 (argument)
greet(“李四”);
“`

6.2 函数表达式 (Function Expression)

将一个匿名函数(没有名字的函数)赋值给一个变量。

“`javascript
const add = function(a, b) {
return a + b; // return 语句用于返回函数的结果
};

let sum = add(5, 3); // 调用函数并将返回值赋给 sum
console.log(sum); // 输出: 8
“`

函数声明 vs 函数表达式: 主要区别在于提升 (Hoisting)。函数声明会被提升到其作用域的顶部,意味着你可以在声明之前调用它。而函数表达式(用 letconst 声明)不会被提升,必须在声明之后才能调用。通常建议将函数声明放在调用之前,以保持代码清晰。

6.3 箭头函数 (Arrow Functions – ES6)

提供了一种更简洁的函数写法,尤其适用于简单的函数和回调函数。

“`javascript
// 传统函数表达式
const multiply = function(a, b) {
return a * b;
};

// 箭头函数 (基本形式)
const multiplyArrow = (a, b) => {
return a * b;
};

// 如果函数体只有一条 return 语句,可以省略 {} 和 return
const subtract = (a, b) => a – b;

// 如果只有一个参数,可以省略参数的 ()
const square = x => x * x;

// 如果没有参数,需要写一对空 ()
const sayHi = () => console.log(“Hi!”);

console.log(multiplyArrow(4, 5)); // 20
console.log(subtract(10, 4)); // 6
console.log(square(9)); // 81
sayHi(); // Hi!
“`

箭头函数还有一个重要的特性:它们不绑定自己的 this 值,this 的值继承自外围作用域。这在处理事件监听器和回调函数时非常有用,但对于初学者,可以暂时不必深入 this 的复杂性。

6.4 参数与返回值

  • 参数 (Parameters): 函数定义时列出的变量名,用于接收传入的数据。
  • 参数 (Arguments): 调用函数时实际传入的值。
  • return 语句: 指定函数执行后返回的值。如果函数没有 return 语句,或者 return 后面没有值,它会默认返回 undefined。一个函数只能有一个 return 语句被执行(一旦执行 return,函数就结束了)。

“`javascript
function checkAge(age) {
if (age >= 18) {
return “允许访问”; // 如果满足条件,返回字符串并结束函数
} else {
return “禁止访问”; // 否则,返回这个字符串并结束函数
}
console.log(“这行代码永远不会执行”);
}

let accessStatus = checkAge(20);
console.log(accessStatus); // 输出: 允许访问

let accessStatus2 = checkAge(15);
console.log(accessStatus2); // 输出: 禁止访问

function noReturnValue() {
console.log(“这个函数没有返回值”);
}
let result = noReturnValue();
console.log(result); // 输出: undefined
“`

6.5 作用域 (Scope)

作用域决定了变量和函数的可访问性(在哪里可以被使用)。

  • 全局作用域 (Global Scope): 在所有函数外部声明的变量拥有全局作用域,可以在代码的任何地方被访问。应尽量避免过多使用全局变量,以防命名冲突和难以追踪的 bug。
  • 局部作用域 (Local Scope / Function Scope): 在函数内部声明的变量(使用 let, const, var)拥有局部作用域,只能在该函数内部访问。
  • 块级作用域 (Block Scope – ES6): 使用 letconst 在代码块(如 if 语句、for 循环的 {})内声明的变量,只在该代码块内部可访问。var 不具有块级作用域。

“`javascript
let globalVar = “我是全局变量”; // 全局作用域

function myFunction() {
let localVar = “我是局部变量”; // 局部作用域
console.log(globalVar); // 可以访问全局变量
console.log(localVar); // 可以访问局部变量

if (true) {
    let blockVar = "我是块级作用域变量 (let)"; // 块级作用域
    const blockConst = "我也是块级作用域 (const)";
    var functionScopedVar = "我是函数作用域变量 (var)"; // var 没有块级作用域
    console.log(blockVar);
    console.log(blockConst);
}
// console.log(blockVar); // 错误!在块外部无法访问 blockVar
// console.log(blockConst); // 错误!
console.log(functionScopedVar); // 可以访问,因为 var 是函数作用域

}

myFunction();
console.log(globalVar); // 可以访问全局变量
// console.log(localVar); // 错误!在函数外部无法访问局部变量
// console.log(functionScopedVar); // 错误!
“`

理解作用域对于避免变量冲突和编写健壮的代码至关重要。优先使用 letconst 来利用块级作用域。


第七章:数据结构:数组与对象 – 组织你的数据

7.1 数组 (Arrays)

数组是有序的值的列表。数组中的每个值称为一个元素,每个元素都有一个从 0 开始的索引 (index)

“`javascript
// 创建数组 (字面量语法 – 推荐)
let fruits = [“苹果”, “香蕉”, “橙子”];
let numbers = [1, 2, 3, 4, 5];
let mixed = [“文本”, 100, true, null, { name: “对象” }]; // 可以包含不同类型的数据

// 访问数组元素 (通过索引)
console.log(fruits[0]); // 输出: 苹果 (第一个元素的索引是 0)
console.log(fruits[1]); // 输出: 香蕉
console.log(fruits[2]); // 输出: 橙子
console.log(fruits[3]); // 输出: undefined (索引超出范围)

// 修改数组元素
fruits[1] = “芒果”;
console.log(fruits); // 输出: [“苹果”, “芒果”, “橙子”]

// 获取数组长度 (元素个数)
console.log(fruits.length); // 输出: 3

// 常用数组方法 (方法是可以在对象/数组上执行的函数)
fruits.push(“草莓”); // 在末尾添加元素
console.log(fruits); // 输出: [“苹果”, “芒果”, “橙子”, “草莓”]
console.log(fruits.length); // 输出: 4

let removedFruit = fruits.pop(); // 移除并返回末尾的元素
console.log(removedFruit); // 输出: 草莓
console.log(fruits); // 输出: [“苹果”, “芒果”, “橙子”]

fruits.unshift(“西瓜”); // 在开头添加元素
console.log(fruits); // 输出: [“西瓜”, “苹果”, “芒果”, “橙子”]

let shiftedFruit = fruits.shift(); // 移除并返回开头的元素
console.log(shiftedFruit); // 输出: 西瓜
console.log(fruits); // 输出: [“苹果”, “芒果”, “橙子”]

console.log(fruits.indexOf(“芒果”)); // 查找元素的索引,输出: 1
console.log(fruits.indexOf(“葡萄”)); // 找不到,返回 -1

// 使用 for…of 遍历数组
for (let fruit of fruits) {
console.log(我喜欢吃 ${fruit});
}

// 使用 forEach 方法遍历数组 (接收一个回调函数)
fruits.forEach(function(fruit, index) {
console.log(索引 ${index}: ${fruit});
});
// 使用箭头函数更简洁
fruits.forEach((fruit, index) => console.log(索引 ${index}: ${fruit}));
“`

数组还有很多其他强大的方法,如 slice, splice, map, filter, reduce 等,这些可以在后续学习中深入探索。

7.2 对象 (Objects) – 再深入

对象是无序键值对 (key-value pair) 的集合。键 (key) 通常是字符串(或者 Symbol),值 (value) 可以是任何数据类型。

“`javascript
// 创建对象 (字面量语法 – 推荐)
let car = {
make: “Toyota”,
model: “Camry”,
year: 2022,
color: “red”,
isRunning: false,
start: function() { // 对象的方法
this.isRunning = true; // this 指向当前对象 (car)
console.log(“引擎启动!”);
},
stop: function() {
this.isRunning = false;
console.log(“引擎关闭!”);
},
// 键也可以用引号包裹,特别是包含特殊字符或空格时
“fuel type”: “Gasoline”
};

// 访问属性
console.log(car.make); // 点表示法
console.log(car[“model”]); // 方括号表示法 (键是字符串)
console.log(car[“fuel type”]); // 访问带特殊字符的键,必须用方括号

// 修改属性
car.color = “blue”;
console.log(car.color); // 输出: blue

// 添加新属性
car.owner = “Alice”;
console.log(car.owner); // 输出: Alice

// 调用方法
car.start(); // 输出: 引擎启动!
console.log(car.isRunning); // 输出: true
car.stop(); // 输出: 引擎关闭!
console.log(car.isRunning); // 输出: false

// 使用 for…in 遍历对象属性
for (let key in car) {
// 最好检查属性是否是对象自身的,而不是继承来的
if (car.hasOwnProperty(key)) {
console.log(${key} -> ${car[key]});
}
}
// 输出类似 (顺序可能不同):
// make -> Toyota
// model -> Camry
// year -> 2022
// color -> blue
// isRunning -> false
// start -> function() { … }
// stop -> function() { … }
// fuel type -> Gasoline
// owner -> Alice
“`

对象是构建复杂数据结构和模拟现实世界事物的基础。


第八章:与网页交互:DOM 基础

到目前为止,我们主要在控制台打印信息。JavaScript 最强大的能力之一是操作网页内容。这是通过 DOM (Document Object Model) 实现的。

DOM 是浏览器为 HTML 文档创建的一个树状结构模型。每个 HTML 元素、属性、文本节点都对应 DOM 树中的一个节点 (node)。JavaScript 可以通过 DOM API 来访问和修改这些节点,从而改变网页的外观和内容。

8.1 选取 HTML 元素

首先,需要选中你想要操作的 HTML 元素。常用的方法有:

  • document.getElementById(id): 通过元素的 id 属性选取,返回单个元素。ID 在一个页面中应该是唯一的。

    html
    <h1 id="main-title">我是标题</h1>
    <p id="intro">这是一段介绍文字。</p>

    “`javascript
    const mainTitle = document.getElementById(“main-title”);
    const introParagraph = document.getElementById(“intro”);

    console.log(mainTitle); // 输出 HTMLHeadingElement 对象
    console.log(introParagraph); // 输出 HTMLParagraphElement 对象
    “`

  • document.querySelector(selector): 使用 CSS 选择器选取第一个匹配的元素。非常灵活强大。

    html
    <div class="content">
    <p>第一个段落</p>
    <p class="highlight">第二个段落</p>
    <button>按钮</button>
    </div>

    “`javascript
    const firstParagraph = document.querySelector(“.content p”); // 选取 .content 下的第一个 p
    const highlighted = document.querySelector(“.highlight”); // 选取 class=”highlight” 的元素
    const button = document.querySelector(“button”); // 选取第一个 button 元素
    const titleById = document.querySelector(“#main-title”); // 也可以用 ID 选择器

    console.log(firstParagraph);
    console.log(highlighted);
    “`

  • document.querySelectorAll(selector): 使用 CSS 选择器选取所有匹配的元素,返回一个 NodeList (类似数组的对象)。

    html
    <ul>
    <li class="item">列表项 1</li>
    <li class="item">列表项 2</li>
    <li>列表项 3</li>
    </ul>

    “`javascript
    const listItems = document.querySelectorAll(“li”); // 选取所有 li
    const specificItems = document.querySelectorAll(“.item”); // 选取所有 class=”item” 的 li

    console.log(listItems.length); // 输出: 3
    console.log(specificItems.length); // 输出: 2

    // NodeList 可以像数组一样使用 forEach 遍历
    listItems.forEach(function(item, index) {
    console.log(列表项 ${index}:, item);
    });

    // 也可以用 for…of 遍历
    for (let item of specificItems) {
    console.log(“特定项:”, item);
    }
    “`

8.2 修改元素内容

  • element.textContent: 获取或设置元素的纯文本内容(忽略 HTML 标签)。

    javascript
    const mainTitle = document.getElementById("main-title");
    console.log(mainTitle.textContent); // 输出: 我是标题
    mainTitle.textContent = "新的标题!"; // 修改标题文本

  • element.innerHTML: 获取或设置元素的包含 HTML 标签的内容。注意: 直接设置 innerHTML 可能存在安全风险 (XSS – Cross-Site Scripting),如果内容来自用户输入,需要谨慎处理,避免注入恶意脚本。

    javascript
    const introParagraph = document.getElementById("intro");
    introParagraph.innerHTML = "这是<strong>加粗</strong>的介绍文字。"; // 可以插入 HTML 标签

8.3 修改元素样式

可以通过元素的 style 属性来修改 CSS 样式。属性名需要使用驼峰命名法(如 backgroundColor 对应 CSS 的 background-color)。

“`javascript
const mainTitle = document.getElementById(“main-title”);

mainTitle.style.color = “blue”; // 设置文字颜色
mainTitle.style.backgroundColor = “#eee”; // 设置背景色
mainTitle.style.padding = “10px”;
mainTitle.style.borderBottom = “2px solid darkblue”; // 设置下边框
“`

8.4 处理事件 (Event Handling)

事件是用户在网页上的操作(如点击、鼠标移动、键盘按下)或浏览器自身发生的事情(如页面加载完成)。我们可以让 JavaScript 对这些事件做出响应。

最常用的方法是 element.addEventListener(eventName, eventHandler):

  • eventName: 事件名称(字符串),如 "click", "mouseover", "keydown".
  • eventHandler: 事件发生时要执行的函数(回调函数)。

“`html

“`

“`javascript
const myButton = document.getElementById(“myButton”);
const messageArea = document.getElementById(“message”);

// 为按钮添加一个点击事件监听器
myButton.addEventListener(“click”, function() {
// 当按钮被点击时,这个函数会被执行
messageArea.textContent = “按钮被点击了! 时间:” + new Date();
myButton.style.backgroundColor = “lightgreen”;
});

// 添加鼠标悬停事件
myButton.addEventListener(“mouseover”, () => {
messageArea.textContent = “鼠标悬停在按钮上…”;
myButton.style.fontWeight = “bold”;
});

// 添加鼠标离开事件
myButton.addEventListener(“mouseout”, () => {
messageArea.textContent = “”; // 清空消息
myButton.style.fontWeight = “normal”;
myButton.style.backgroundColor = “”; // 恢复默认背景色
});
“`

现在,当你用浏览器打开包含这段 HTML 和 JS 的页面时,点击按钮、鼠标移入移出都会触发相应的 JS 代码,改变页面内容和样式!


第九章:下一步与学习资源

恭喜你!你已经完成了 JavaScript 新手入门的核心内容。你现在应该对 JavaScript 的基本概念、语法和如何在网页中使用它有了初步的了解。

接下来该学什么?

  • 深入 DOM 操作: 学习如何创建、添加、删除 HTML 元素,处理更复杂的事件(如表单提交、键盘事件),操作元素的属性和类 (classList)。
  • 异步 JavaScript: 理解 JavaScript 的单线程和事件循环机制,学习处理耗时操作(如从服务器获取数据)的方法:回调函数、Promises、async/await (现代推荐)。
  • 错误处理: 使用 try...catch 语句优雅地处理代码中可能出现的错误。
  • ES6+ 新特性: 深入学习 ES6 及之后版本引入的更多特性,如解构赋值、扩展运算符、模块化 (import/export) 等,它们能让你的代码更简洁、更强大。
  • 数据请求 (AJAX/Fetch): 学习如何使用 Fetch API 或 XMLHttpRequest (旧) 从服务器异步获取数据。
  • 面向对象编程 (OOP) 深入: 学习 JavaScript 的原型链、类 (ES6 class 语法糖)、继承等。
  • 实践!实践!实践! 理论学习后,最重要的就是动手编写代码。尝试做一些小项目:待办事项列表、简单的计算器、图片库、简单的表单验证等。

推荐学习资源:

  1. MDN Web Docs (Mozilla Developer Network): 最权威、最全面的 Web 技术文档,包括详尽的 JavaScript 参考。当你对某个概念或方法不确定时,首先查阅 MDN。(https://developer.mozilla.org/zh-CN/docs/Web/JavaScript)
  2. freeCodeCamp: 提供免费的交互式编程课程,包含大量的 JavaScript 练习和项目。(https://www.freecodecamp.org/)
  3. JavaScript.info: 一个现代化的、内容非常深入的 JavaScript 教程网站。(https://javascript.info/)
  4. W3Schools: 提供简洁的入门教程和在线实例。(内容可能不如 MDN 严谨,但适合快速查找)(https://www.w3schools.com/js/)
  5. 书籍: 《JavaScript 高级程序设计》(红宝书)、《你不知道的 JavaScript》系列等经典书籍。

结语

学习编程是一个持续的过程,尤其是像 JavaScript 这样快速发展的语言。不要害怕犯错,错误是学习过程中宝贵的一部分。多动手实践,多查阅文档,多思考,多向社区提问。

希望这篇详尽的入门教程能为你打开 JavaScript 的大门,并激发你继续探索 Web 开发的兴趣。祝你编程愉快!

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部