JS 教程入门必看 – wiki基地


JS 教程入门必看:从零到精通的基础之路

欢迎来到充满活力的前端世界!如果你对构建交互式的网页感兴趣,或者想踏入软件开发的大门,那么 JavaScript (JS) 将是你旅程中不可或缺的一步。它不仅是网页开发的基石之一,更是目前应用最广泛、生态最活跃的编程语言之一。

本篇文章将作为你的 JavaScript 入门指南,从最基础的概念讲起,逐步深入核心知识,帮助你建立坚实的JS基础。请记住,编程是一场马拉松,而非短跑。耐心、实践和持续学习是成功的关键。

废话不多说,让我们开始这段精彩的编程之旅吧!

第一章:初识 JavaScript – 它是什么?为什么学?

1.1 JavaScript 的定义与定位

简单来说,JavaScript 是一种轻量级、解释型、动态类型的编程语言。最初设计用于在网页浏览器中运行,使得网页具备交互性,不再是静态的信息展示。随着技术的发展,JavaScript 的应用范围早已超出了浏览器,扩展到了服务器端(Node.js)、移动应用开发(React Native, Ionic)、桌面应用开发(Electron)、甚至物联网等领域。

  • 解释型:JS 代码不需要预先编译成机器码,而是由解释器逐行执行。这使得开发和调试更加便捷。
  • 动态类型:变量的类型在运行时才能确定,同一个变量可以存储不同类型的数据。这提供了灵活性,但也可能带来一些潜在的问题(比如类型错误),需要开发者多加注意。
  • 轻量级:相对于一些大型的企业级语言(如 Java, C++),JS 的语法相对简洁易学,非常适合作为入门语言。

1.2 JavaScript 的发展与标准 (ECMAScript)

JavaScript 最初由 Brendan Eich 在网景公司(Netscape)于 1995 年的 10 天内设计完成,最初命名为 Mocha,后改为 LiveScript,最终更名为 JavaScript。这个名字的改变与当时流行的 Java 语言有关,网景希望借助 Java 的声势推广自家的语言。

为了标准化这门语言,ECMA 国际(一个标准组织)制定了 ECMAScript(简称 ES)规范。JavaScript 是 ECMAScript 规范的一种实现。我们常听到的 ES5、ES6 (ES2015)、ES7 (ES2016) 等,指的就是不同版本的 ECMAScript 规范。学习 JS,实际上就是学习 ECMAScript 规范的核心语法,以及浏览器或 Node.js 等宿主环境提供的特定 API(例如浏览器中的 DOM API 用于操作网页元素)。

现代 JavaScript 开发通常遵循最新的 ECMAScript 标准(目前主流是 ES6 及以后版本),这些版本引入了许多重要的语法糖和新特性,极大地提高了开发效率和代码可读性。作为入门者,我们将从最基础的 ES5 语法开始,逐步接触 ES6 的常用特性。

1.3 JavaScript 在 Web 开发中的地位

在前端领域,HTML、CSS 和 JavaScript 是构建现代网页的三大核心技术:

  • HTML (HyperText Markup Language):负责页面的结构和内容(骨架)。
  • CSS (Cascading Style Sheets):负责页面的样式和布局(皮囊)。
  • JavaScript:负责页面的行为和交互(灵魂)。

JS 可以修改 HTML 内容、改变 CSS 样式、响应用户的操作(如点击按钮、提交表单)、从服务器获取数据并更新页面等等。正是有了 JavaScript,网页才变得生动、智能和富有吸引力。

1.4 为什么选择学习 JavaScript?

  • 应用广泛:无论前端还是后端,JS 都有广泛的应用,技能迁移性强。
  • 易于入门:语法相对灵活,学习资源丰富,社区活跃,遇到问题容易找到解决方案。
  • 前景光明:JS 生态持续繁荣,各种框架和库层出不穷(React, Vue, Angular, Node.js 等),提供了丰富的职业发展方向。
  • 全栈潜力:掌握 JS,你可以在前端和后端都进行开发,成为一名“全栈工程师”。

总而言之,学习 JavaScript 是进入现代软件开发领域的一张“门票”,无论你的最终目标是什么,掌握它都将为你打开无数扇门。

第二章:踏出第一步 – 准备你的学习环境

学习编程,首先需要一个可以编写、运行和调试代码的环境。幸运的是,学习 JavaScript 非常简单,你可能已经拥有了所需的大部分工具。

2.1 所需工具

  1. 现代网页浏览器:如 Chrome, Firefox, Edge, Safari。这些浏览器内置了 JavaScript 引擎(如 V8, SpiderMonkey)来执行 JS 代码,并提供了强大的开发者工具。
  2. 文本编辑器或集成开发环境 (IDE):用于编写代码。

2.2 使用浏览器控制台 (Console)

这是学习 JS 最快捷的方式。大多数现代浏览器都提供了开发者工具,你可以直接在其中输入并运行 JavaScript 代码。

如何打开控制台:

  • 在网页上右键,选择“检查”(Inspect)或“审查元素”。
  • 在打开的开发者工具窗口中,切换到“Console”(控制台)选项卡。

在控制台中尝试:

输入以下代码并按回车键:

javascript
console.log("你好,JavaScript!"); // 在控制台输出信息
alert("这是一个弹窗!"); // 弹出提示框

console.log() 是一个非常常用的函数,用于在控制台输出信息,这对于调试代码非常有帮助。alert() 用于在浏览器中弹出一个简单的警告框。

控制台是一个很好的实验场,你可以随时输入一小段代码来测试某个语法或概念。

2.3 选择一个好的代码编辑器

虽然记事本也能写代码,但专业的代码编辑器能提供语法高亮、自动补全、错误检查等功能,极大地提升开发效率和体验。

推荐的编辑器(免费且流行):

  • VS Code (Visual Studio Code):微软出品,功能强大,轻量级,插件生态丰富,强烈推荐新手使用。
  • Sublime Text:轻量级,启动快,界面简洁。
  • Atom:GitHub 出品,可高度定制。
  • Notepad++ (仅限 Windows):简单易用。

选择一个你用着顺手的即可。VS Code 是目前最主流的选择,安装简单,提供中文界面,并且有很多针对前端开发的实用插件。

2.4 创建第一个 HTML 文件并链接 JS

JavaScript 通常与 HTML 和 CSS 结合使用。你可以在 HTML 文件中直接编写 JS 代码,或者链接一个外部的 JS 文件。推荐使用外部文件,这样可以保持代码的组织性和可维护性。

  1. 创建一个文件夹:例如命名为 my-js-project
  2. 在该文件夹中创建两个文件
    • index.html
    • script.js
  3. 编辑 index.html

    “`html
    <!DOCTYPE html>




    我的第一个JS页面


    <h1>你好,世界!</h1>
    <p>这是我的第一个包含 JavaScript 的页面。</p>
    
    <!-- 建议将 <script> 标签放在 <body> 结束标签之前 -->
    <!-- 这样可以确保 HTML 内容加载完成后再执行 JS -->
    <script src="script.js"></script>
    



    “`

  4. 编辑 script.js

    “`javascript
    // 这是一个单行注释,用于解释代码
    console.log(“script.js 文件已成功加载并执行!”);

    // 你可以在这里写更多的 JS 代码
    // 例如,改变页面标题
    document.title = “页面标题被JS改变了!”;

    // 例如,弹出一个友好的问候
    alert(“欢迎来到我的页面!”);
    “`

  5. 运行 index.html:用浏览器直接打开 index.html 文件。你应该会看到页面内容,一个弹窗,并且在浏览器的控制台中看到输出信息。

通过这个简单的例子,你就成功地在网页中运行了你的第一段 JavaScript 代码!

第三章:JS 基础:构建代码的积木

掌握任何编程语言,都需要先理解其最基本的构成要素。本章将介绍 JavaScript 的核心语法概念。

3.1 注释 (Comments)

注释是写在代码中用于解释代码用途、功能或思路的文本,它不会被 JavaScript 解释器执行。养成写注释的好习惯对于自己回顾代码或与他人协作都非常重要。

  • 单行注释:以 // 开始,直到行末。

    javascript
    // 这是一行注释
    let name = "张三"; // 这也是注释

  • 多行注释:以 /* 开始,以 */ 结束。

    javascript
    /*
    这是多行注释
    可以跨越多行来描述一个复杂的逻辑块
    */
    let age = 30;

3.2 变量 (Variables)

变量就像一个容器,用于存储数据。在使用变量之前,你需要先声明(定义)它。在现代 JavaScript 中,我们主要使用 letconst 来声明变量。

  • let:声明一个块级作用域的变量。可以重新赋值。

    “`javascript
    let message = “Hello”;
    message = “World”; // 可以修改
    console.log(message); // 输出 “World”

    // 在同一个作用域内不能重复声明
    // let message = “Again”; // 会报错
    “`

  • const:声明一个块级作用域的常量。一旦赋值后,不能再重新赋值。常用于声明不会改变的值。

    “`javascript
    const PI = 3.14159;
    // PI = 3.14; // 尝试修改常量,会报错

    const user = { name: “李四” };
    user.name = “王五”; // 注意:const 保证变量指向的内存地址不变,但如果变量指向的是对象或数组,可以修改其内部属性/元素。
    console.log(user.name); // 输出 “王五”

    // const user = { age: 25 }; // 尝试重新赋值整个对象,会报错
    “`

  • var:声明一个函数作用域的变量。var 是 ES6 之前唯一的声明方式,存在一些问题(如变量提升和作用域混乱),在现代 JS 开发中,推荐优先使用 letconst

    javascript
    var oldVar = "这是老方法";
    // var 存在变量提升(hoisting)等特性,初学者了解即可,重点掌握 let 和 const。

变量命名规则:

  • 名称可以包含字母、数字、$、_。
  • 名称不能以数字开头。
  • 名称不能是 JS 的保留字(如 if, for, function 等)。
  • 区分大小写 (myVarmyvar 是不同的变量)。
  • 推荐使用驼峰命名法 (camelCase):第一个单词小写,后面每个单词的首字母大写,例如 firstName, getUserData

3.3 数据类型 (Data Types)

JavaScript 中的数据可以分为两大类:原始类型 (Primitive types)对象类型 (Object type)

原始类型 (共 7 种):

  1. string:表示文本。使用单引号 (')、双引号 (") 或反引号 (`) 包含。

    javascript
    let str1 = '这是一个字符串';
    let str2 = "这也是一个字符串";
    let str3 = `你好, ${name}!`; // 模板字符串 (template literals),支持嵌入变量
    console.log(str3);

  2. number:表示数字,包括整数和浮点数。

    javascript
    let num1 = 10; // 整数
    let num2 = 3.14; // 浮点数
    let num3 = NaN; // Not a Number,表示非法的数学运算结果
    let num4 = Infinity; // 无穷大

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

    javascript
    let isloggedIn = true;
    let hasPermission = false;

  4. null:表示一个空值或不存在的对象。需要显式赋值为 null

    javascript
    let data = null; // 表示 data 变量没有指向任何对象

  5. undefined:表示一个未定义的值。通常是变量被声明了但没有赋值时的默认值,或者函数没有返回值时。

    “`javascript
    let score; // 变量声明了但没有赋值,默认值为 undefined
    console.log(score); // 输出 undefined

    function greet() {
    // 没有 return 语句,默认返回 undefined
    }
    console.log(greet()); // 输出 undefined
    ``
    *
    nullundefined的区别是一个常见的面试题。简单来说,null是一个被有意设置的空值,而undefined是变量缺少值时的状态。虽然typeof null的结果是“object”`(这是 JS 历史上的一个 bug),但它们是不同的。

  6. symbol (ES6 新增):表示唯一的、不可变的值。常用于对象的属性名,避免属性名冲突。

    javascript
    const id = Symbol('id');
    const anotherId = Symbol('id');
    console.log(id === anotherId); // 输出 false

  7. bigint (ES11 新增):表示任意精度的整数。用于处理大于 number 类型能表示的最大安全整数(2^53 - 1)的数值。

    javascript
    const bigNumber = 1234567890123456789012345678901234567890n; // 末尾加 n 表示 BigInt

对象类型 (Object type):表示更复杂的复合数据结构。包括:

  • object:广义上的对象,键值对的集合。例如:普通对象、数组、函数等。

    • 普通对象:无序的键值对集合,用于存储结构化数据。

      javascript
      let person = {
      name: "张三",
      age: 30,
      isStudent: false
      };
      console.log(person.name); // 访问属性:点表示法
      console.log(person['age']); // 访问属性:方括号表示法
      person.city = "北京"; // 添加新属性

      * 数组 (Array):有序的元素集合,用索引访问。

      javascript
      let colors = ["红", "绿", "蓝"];
      console.log(colors[0]); // 访问第一个元素 (索引从0开始)
      console.log(colors.length); // 数组长度
      colors.push("黄"); // 在末尾添加元素

      * 函数 (Function):可执行的代码块。函数在 JS 中也是一种特殊的对象。

      javascript
      function sayHello(name) {
      return `你好, ${name}!`;
      }
      let greeting = sayHello("李四");
      console.log(greeting);

  • function:虽然函数在技术上是对象类型,但 typeof 操作符对函数会返回 "function",这表明了函数在 JS 中的特殊地位(它们是可调用的对象)。

typeof 操作符:用于检测一个变量或表达式的数据类型。

javascript
console.log(typeof "Hello"); // string
console.log(typeof 123); // number
console.log(typeof true); // boolean
console.log(typeof null); // object (历史遗留问题)
console.log(typeof undefined); // undefined
console.log(typeof Symbol()); // symbol
console.log(typeof 123n); // bigint
console.log(typeof {}); // object
console.log(typeof []); // object
console.log(typeof function() {}); // function

3.4 运算符 (Operators)

运算符用于对变量或值执行操作。

  • 算术运算符+ (加), - (减), * (乘), / (除), % (取模/余数), ** (幂运算,ES6)

    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
    console.log(a ** b); // 1000 (10的3次方)

    * 注意 + 在字符串中是拼接作用:"Hello" + " " + "World" 结果是 "Hello World"。如果数字和字符串相加,数字会被转换为字符串进行拼接。

  • 赋值运算符= (赋值), +=, -=, *=, /=, %=, **=

    javascript
    let x = 5;
    x += 3; // 等同于 x = x + 3; x 现在是 8
    x *= 2; // 等同于 x = x * 2; x 现在是 16

  • 比较运算符:用于比较两个值,返回布尔值 (truefalse)。

    • == (相等,会进行类型转换)
    • != (不等,会进行类型转换)
    • === (严格相等,不进行类型转换,要求值和类型都相等) – 强烈推荐使用
    • !== (严格不等,不进行类型转换) – 强烈推荐使用
    • > (大于), < (小于), >= (大于等于), <= (小于等于)

    javascript
    console.log(5 == '5'); // true (会把 '5' 转成 5)
    console.log(5 === '5'); // false (类型不同)
    console.log(10 > 5); // true
    console.log(null == undefined); // true (特殊情况)
    console.log(null === undefined); // false

    * 理解 ===== 的区别至关重要,=== 是更安全的比较方式。

  • 逻辑运算符

    • && (逻辑与):如果左侧为真,则返回右侧的值;否则返回左侧的值。常用于判断多个条件是否都为真。
    • || (逻辑或):如果左侧为真,则返回左侧的值;否则返回右侧的值。常用于判断多个条件是否至少一个为真。
    • ! (逻辑非):取反。

    “`javascript
    let isAdult = true;
    let isStudent = false;
    console.log(isAdult && isStudent); // false (true 与 false = false)
    console.log(isAdult || isStudent); // true (true 或 false = true)
    console.log(!isAdult); // false (非 true = false)

    // 短路评估 (Short-circuit evaluation)
    let y = 0;
    let result = (10 > 5) || (y++); // 左侧为真,|| 后面的表达式不再执行
    console.log(result); // true
    console.log(y); // 0

    let z = 0;
    let outcome = (10 < 5) && (z++); // 左侧为假,&& 后面的表达式不再执行
    console.log(outcome); // false
    console.log(z); // 0
    “`

  • 一元运算符:只作用于一个操作数,如 ++ (自增), -- (自减), + (转换为数字), - (取负)

    javascript
    let counter = 10;
    counter++; // counter 现在是 11
    console.log(-"5"); // -5 (字符串转数字并取负)

  • 三元条件运算符:一个简写形式的 if/else 语句。

    • 语法:condition ? expressionIfTrue : expressionIfFalse

    javascript
    let age = 18;
    let status = (age >= 18) ? "成年" : "未成年";
    console.log(status); // 输出 "成年"

3.5 类型转换 (Type Coercion)

JavaScript 是一种弱类型语言,它会在不同数据类型之间进行自动转换(隐式转换)。这有时会带来便利,但也可能导致意想不到的结果。

  • 隐式转换:发生在运算符操作不同类型的数据时,JS 会尝试将它们转换为相同类型。
    • 数字与字符串相加:数字转字符串进行拼接。1 + "2" -> "12"
    • 数字与布尔值相加:布尔值转数字 (true 为 1, false 为 0)。1 + true -> 2
    • 使用 == 比较时。5 == '5' -> true
  • 显式转换:开发者主动进行的类型转换。

    • 转换为字符串:String(value)value.toString() (除 nullundefined)
    • 转换为数字:Number(value), parseInt(string), parseFloat(string)
    • 转换为布尔值:Boolean(value) 或使用 !!value

    “`javascript
    console.log(String(123)); // “123”
    console.log((123).toString()); // “123”

    console.log(Number(“456”)); // 456
    console.log(parseInt(“100px”)); // 100 (解析到非数字字符停止)
    console.log(parseFloat(“3.14”)); // 3.14
    console.log(Number(“hello”)); // NaN

    console.log(Boolean(0)); // false
    console.log(Boolean(“”)); // false
    console.log(Boolean(null)); // false
    console.log(Boolean(undefined)); // false
    console.log(Boolean(NaN)); // false
    console.log(Boolean(” “)); // true (非空字符串)
    console.log(Boolean(10)); // true (非零数字)
    ``
    * 在进行比较和运算时,了解 JS 的类型转换规则非常重要。对于初学者,**强烈建议使用
    ===` (严格相等) 来避免不必要的类型转换带来的问题**。

第四章:控制代码流程 – 让程序“思考”

默认情况下,JS 代码是按照书写顺序从上到下依次执行的。但很多时候,我们需要根据条件来决定执行哪些代码,或者重复执行某段代码。这就需要使用控制流程语句。

4.1 条件语句 (Conditional Statements)

根据条件的真假来选择执行不同的代码块。

  • if 语句:当条件为真时执行代码块。

    javascript
    let temperature = 25;
    if (temperature > 20) {
    console.log("天气有点热。");
    }

  • if...else 语句:当条件为真时执行第一个代码块,否则执行第二个代码块。

    javascript
    let age = 16;
    if (age >= 18) {
    console.log("你已成年。");
    } else {
    console.log("你未成年。");
    }

  • if...else if...else 语句:用于处理多个互斥的条件。

    javascript
    let score = 85;
    if (score >= 90) {
    console.log("优秀");
    } else if (score >= 80) {
    console.log("良好");
    } else if (score >= 60) {
    console.log("及格");
    } else {
    console.log("不及格");
    }

4.2 switch 语句

当需要根据一个变量的不同值执行不同的代码块时,switch 语句是 if...else if 的另一种选择,尤其适用于多个固定值判断的情况。

javascript
let day = "星期三";
switch (day) {
case "星期一":
console.log("蓝色星期一");
break; // break 关键字用于跳出 switch 语句
case "星期五":
console.log("快乐星期五");
break;
case "星期六":
case "星期日": // 多个 case 可以共用一个代码块
console.log("周末愉快!");
break;
default: // 如果所有 case 都不匹配,则执行 default 块
console.log("工作日");
// default 块通常放在最后,不需要 break
}

* break 语句非常重要,它会结束当前的 switch 执行。如果没有 break,匹配到一个 case 后会继续执行后面的 case 块(称为“穿透”或“fall-through”),直到遇到 breakswitch 结束。

4.3 循环语句 (Loops)

循环用于重复执行一段代码,直到满足或不再满足某个条件。

  • for 循环:最常用的循环,适用于已知循环次数或有明确循环范围的情况。

    javascript
    // 语法:for (初始化; 条件; 递增/递减) { // 循环体 }
    for (let i = 0; i < 5; i++) {
    console.log("这是第 " + (i + 1) + " 次循环");
    }
    // 输出:
    // 这是第 1 次循环
    // 这是第 2 次循环
    // ...
    // 这是第 5 次循环

  • while 循环:当条件为真时重复执行代码块。适用于循环次数未知,只知道循环结束条件的情况。

    javascript
    let count = 0;
    while (count < 3) {
    console.log("count: " + count);
    count++; // 必须要有更新条件的语句,否则可能成为无限循环
    }
    // 输出:
    // count: 0
    // count: 1
    // count: 2

  • do...while 循环:先执行一次代码块,然后检查条件,如果条件为真,则重复执行。保证循环体至少被执行一次。

    javascript
    let i = 0;
    do {
    console.log("i: " + i);
    i++;
    } while (i < 3);
    // 输出:
    // i: 0
    // i: 1
    // i: 2

  • for...in 循环:遍历对象的可枚举属性。

    javascript
    const person = { name: "张三", age: 30 };
    for (const key in person) {
    console.log(key + ": " + person[key]);
    }
    // 输出:
    // name: 张三
    // age: 30

    * for...in 不推荐用于遍历数组,因为它会遍历原型链上的属性,并且顺序可能不是数字索引顺序。

  • for...of 循环 (ES6 新增):遍历可迭代对象(如数组、字符串、Map、Set 等)的元素值。推荐用于遍历数组。

    javascript
    const colors = ["红", "绿", "蓝"];
    for (const color of colors) {
    console.log(color);
    }
    // 输出:
    // 红
    // 绿
    // 蓝

4.4 跳出循环 (breakcontinue)

  • break:立即终止当前循环(或 switch 语句),跳到循环后面的第一行代码。
  • continue:跳过当前循环的剩余部分,进入下一次循环。

“`javascript
// break 示例
for (let i = 0; i < 10; i++) {
if (i === 5) {
break; // 当 i 等于 5 时,立即停止循环
}
console.log(“break 循环:” + i);
}
// 输出:0, 1, 2, 3, 4

// continue 示例
for (let i = 0; i < 5; i++) {
if (i === 2) {
continue; // 当 i 等于 2 时,跳过本次循环的 console.log,直接进入下一次循环 (i=3)
}
console.log(“continue 循环:” + i);
}
// 输出:0, 1, 3, 4
“`

第五章:函数 – 组织和复用你的代码

函数是一段可重复使用的代码块,它执行一个特定的任务。使用函数可以提高代码的可读性、可维护性和复用性。

5.1 声明和调用函数

  • 函数声明 (Function Declaration):使用 function 关键字。

    “`javascript
    function greet(name) { // name 是参数 (parameter)
    console.log(“你好,” + name + “!”);
    }

    greet(“张三”); // 调用函数,传入参数值 (“张三”) 称为实参 (argument)
    greet(“李四”); // 可以多次调用
    “`

  • 函数表达式 (Function Expression):将一个匿名函数赋值给一个变量。

    “`javascript
    const sayBye = function(name) {
    console.log(“再见,” + name + “!”);
    }; // 注意末尾的分号 (;) 是可选的,但建议加上

    sayBye(“王五”);
    “`
    * 函数声明可以在定义之前调用(因为存在函数提升),而函数表达式必须先定义后调用。对于初学者,通常使用函数声明更直观。

  • 箭头函数 (Arrow Function) (ES6 新增):一种更简洁的函数表达式语法。

    “`javascript
    const add = (a, b) => {
    return a + b;
    };

    // 如果函数体只有一行 return 语句,可以进一步简化
    const multiply = (a, b) => a * b;

    // 如果只有一个参数,可以省略圆括号
    const double = num => num * 2;

    // 如果没有参数,需要空圆括号
    const sayHello = () => console.log(“Hello!”);

    console.log(add(5, 3)); // 8
    console.log(multiply(4, 5)); // 20
    console.log(double(7)); // 14
    sayHello(); // Hello!
    ``
    * 箭头函数相比普通函数有一些不同之处(例如
    this` 关键字的绑定方式),但在基础使用场景下,它们提供了一种更简洁的语法。对于简单的回调函数,箭头函数非常方便。

5.2 函数参数和返回值

  • 参数 (Parameters):函数定义时括号中的变量,用于接收传入的数据。
  • 实参 (Arguments):函数调用时传入的实际值。
  • 返回值 (Return Value):函数可以通过 return 关键字返回一个值。如果没有 return 语句或 return 后面没有值,函数默认返回 undefined

    “`javascript
    function sum(a, b) {
    let result = a + b;
    return result; // 返回计算结果
    }

    let total = sum(10, 20); // 调用函数并将返回值赋给变量
    console.log(total); // 30

    function doSomething() {
    console.log(“只执行,不返回特定值”);
    // 没有 return 语句
    }
    console.log(doSomething()); // undefined
    “`

5.3 作用域 (Scope)

作用域决定了变量的可见性和生命周期。在 JS 中主要有两种作用域:

  • 全局作用域 (Global Scope):在函数或块外部声明的变量具有全局作用域,在代码的任何地方都可以访问。应尽量避免滥用全局变量,以免引起命名冲突和维护困难。
  • 局部作用域 (Local Scope)
    • 函数作用域 (Function Scope):使用 var 在函数内部声明的变量具有函数作用域,只能在该函数内部访问。
    • 块级作用域 (Block Scope):使用 letconst 在一对花括号 {} 内声明的变量具有块级作用域,只能在该块内部访问。块可以是 if 语句、for 循环、函数等。

理解作用域对于避免变量命名冲突和理解变量生命周期非常重要。ES6 引入的块级作用域(let/const)是现代 JS 开发中的最佳实践。

“`javascript
let globalVar = “我是全局变量”;

function myFunction() {
let functionVar = “我是函数作用域变量”; // let 具有块级作用域
var oldFunctionVar = “我是老的函数作用域变量”; // var 具有函数作用域
console.log(globalVar); // 可以在函数内访问全局变量
console.log(functionVar);
console.log(oldFunctionVar);

if (true) {
    let blockVar = "我是块级作用域变量"; // 只能在 if 块内访问
    console.log(blockVar);
    console.log(functionVar); // 可以在块内访问函数作用域变量
    console.log(globalVar); // 可以在块内访问全局变量
}
// console.log(blockVar); // 在块外部访问块级变量会报错

}

myFunction();
console.log(globalVar); // 可以在函数外访问全局变量
// console.log(functionVar); // 在函数外访问函数作用域变量会报错
// console.log(oldFunctionVar); // 在函数外访问函数作用域变量会报错
“`

第六章:数组与对象 – 处理集合数据

在实际开发中,我们经常需要处理一组相关的数据。数组和对象是 JavaScript 中用于组织这些集合数据的基本结构。

6.1 数组 (Arrays)

数组是一种有序的集合,其中的每个元素都有一个索引(从 0 开始)。

  • 创建数组

    “`javascript
    // 数组字面量 (推荐)
    let fruits = [“苹果”, “香蕉”, “橘子”];

    // 使用 Array 构造函数 (不常用,有陷阱)
    // let numbers = new Array(1, 2, 3); // 创建包含 1, 2, 3 的数组
    // let strangeArray = new Array(5); // 创建一个长度为 5 的空数组 (注意不是 [5])
    “`

  • 访问数组元素:通过索引访问。

    javascript
    console.log(fruits[0]); // 输出 "苹果"
    console.log(fruits[2]); // 输出 "橘子"
    console.log(fruits[3]); // 输出 undefined (索引越界)

  • 修改数组元素:通过索引赋值。

    javascript
    fruits[1] = "葡萄"; // 将第二个元素改为 "葡萄"
    console.log(fruits); // 输出 ["苹果", "葡萄", "橘子"]

  • 数组长度:使用 .length 属性。

    javascript
    console.log(fruits.length); // 输出 3 (修改后是 3)

  • 添加/删除元素

    • .push(element):在末尾添加一个或多个元素,返回新长度。
    • .pop():删除并返回末尾元素。
    • .unshift(element):在开头添加一个或多个元素,返回新长度。
    • .shift():删除并返回开头元素。

    javascript
    let nums = [1, 2];
    nums.push(3, 4); // nums becomes [1, 2, 3, 4]
    let last = nums.pop(); // last is 4, nums becomes [1, 2, 3]
    nums.unshift(0); // nums becomes [0, 1, 2, 3]
    let first = nums.shift(); // first is 0, nums becomes [1, 2, 3]

  • 常用数组方法

    • .forEach(callback):遍历数组的每个元素,对每个元素执行一次 callback 函数。
    • .map(callback):创建一个新数组,新数组的元素是原数组元素调用 callback 函数的返回值。
    • .filter(callback):创建一个新数组,新数组只包含通过 callback 函数测试的元素。
    • .find(callback):返回数组中满足 callback 函数测试的第一个元素的值,否则返回 undefined
    • .indexOf(element):返回元素第一次出现的索引,否则返回 -1。
    • .includes(element) (ES7):判断数组是否包含某个元素,返回布尔值。

    “`javascript
    let numbers = [1, 2, 3, 4, 5];

    numbers.forEach(function(num) {
    console.log(num * 2); // 输出 2, 4, 6, 8, 10
    });

    let doubled = numbers.map(num => num * 2);
    console.log(doubled); // 输出 [2, 4, 6, 8, 10]

    let evens = numbers.filter(num => num % 2 === 0);
    console.log(evens); // 输出 [2, 4]

    console.log(numbers.includes(3)); // 输出 true
    “`
    * 熟悉这些数组方法能大大提高处理列表数据的效率。

6.2 对象 (Objects)

对象是无序的属性集合,每个属性由键 (key,通常是字符串或 Symbol) 和值 (value,可以是任何数据类型) 组成。对象用于表示现实世界中的实体或复杂的数据结构。

  • 创建对象

    “`javascript
    // 对象字面量 (推荐)
    let car = {
    brand: “Toyota”,
    model: “Camry”,
    year: 2023,
    isElectric: false,
    start: function() { // 属性值也可以是函数 (方法)
    console.log(“Engine started!”);
    }
    };

    // 使用 Object 构造函数 (不常用)
    // let anotherCar = new Object();
    // anotherCar.brand = “Honda”;
    “`

  • 访问对象属性

    • 点表示法 (Dot notation):当键是有效的变量名时使用。object.key
    • 方括号表示法 (Bracket notation):当键包含特殊字符或来自变量时使用。object['key']

    “`javascript
    console.log(car.brand); // 输出 “Toyota”
    console.log(car[‘model’]); // 输出 “Camry”

    let propName = ‘year’;
    console.log(car[propName]); // 使用变量访问属性,输出 2023
    “`

  • 修改/添加属性:通过赋值操作。

    javascript
    car.year = 2024; // 修改属性值
    car.color = "Red"; // 添加新属性
    console.log(car.year); // 2024
    console.log(car.color); // Red

  • 删除属性:使用 delete 运算符。

    javascript
    delete car.isElectric;
    console.log(car.isElectric); // 输出 undefined

  • 调用对象方法

    javascript
    car.start(); // 输出 "Engine started!"

  • 遍历对象属性

    • 使用 for...in 循环 (如前所述)。
    • 使用 Object.keys(object) 获取所有键组成的数组。
    • 使用 Object.values(object) 获取所有值组成的数组。
    • 使用 Object.entries(object) 获取所有键值对 [key, value] 组成的数组。

    ``javascript
    for (const key in car) {
    console.log(
    ${key}: ${car[key]}`);
    }

    console.log(Object.keys(car)); // 输出 [“brand”, “model”, “year”, “color”, “start”]
    console.log(Object.values(car)); // 输出 [“Toyota”, “Camry”, 2024, “Red”, [Function: start]]
    console.log(Object.entries(car)); // 输出 [ [“brand”, “Toyota”], [“model”, “Camry”], … ]
    “`

6.3 数组与对象的结合使用

数组和对象经常嵌套使用,构建更复杂的数据结构,例如:

“`javascript
// 一个包含多个用户对象的数组
let users = [
{ id: 1, name: “Alice”, city: “New York” },
{ id: 2, name: “Bob”, city: “London” },
{ id: 3, name: “Charlie”, city: “New York” }
];

// 访问第二个用户的城市
console.log(users[1].city); // 输出 “London”

// 遍历所有用户,打印他们的名字
users.forEach(user => {
console.log(user.name); // 输出 “Alice”, “Bob”, “Charlie”
});
“`

第七章:JavaScript 与 Web 页面交互 – DOM

前端 JavaScript 最核心的功能之一就是操作网页的内容、结构和样式,这就是通过 DOM (Document Object Model – 文档对象模型) 实现的。

7.1 什么是 DOM?

当你用浏览器打开一个 HTML 页面时,浏览器会解析 HTML 代码,并将其构建成一个树状结构,这个树就是 DOM。树的每个节点都代表 HTML 页面中的一个部分,比如元素 (<div>, <p>)、属性 (id, class)、文本 (Hello World!) 等。

JavaScript 可以通过浏览器提供的 DOM API 来访问和操作这个 DOM 树,从而改变页面的外观和行为。document 对象是 DOM 的入口点,它代表了整个 HTML 文档。

7.2 获取 DOM 元素

在操作元素之前,首先需要找到它们。常用的获取元素的方法:

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

    html
    <div id="myDiv">这是一个 div</div>
    <script>
    const myDiv = document.getElementById('myDiv');
    console.log(myDiv); // 输出获取到的 div 元素
    </script>

  • document.getElementsByClassName(className):通过类名获取一组元素(返回一个类似数组的 HTMLCollection)。

    html
    <p class="myClass">段落 1</p>
    <p class="myClass">段落 2</p>
    <script>
    const paragraphs = document.getElementsByClassName('myClass');
    console.log(paragraphs); // 输出一个包含两个 p 元素的 HTMLCollection
    console.log(paragraphs[0]); // 访问第一个元素
    </script>

  • document.getElementsByTagName(tagName):通过标签名获取一组元素。

    html
    <ul><li>Item 1</li><li>Item 2</li></ul>
    <script>
    const listItems = document.getElementsByTagName('li');
    console.log(listItems.length); // 输出 2
    </script>

  • document.querySelector(selector):使用 CSS 选择器获取第一个匹配的元素。

    html
    <div class="container"><p>第一个段落</p></div>
    <div class="container"><p>第二个段落</p></div>
    <script>
    const firstPara = document.querySelector('.container p');
    console.log(firstPara.textContent); // 输出 "第一个段落"
    </script>

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

    html
    <div class="container"><p>第一个段落</p></div>
    <div class="container"><p>第二个段落</p></div>
    <script>
    const allParas = document.querySelectorAll('.container p');
    console.log(allParas.length); // 输出 2
    allParas.forEach(p => console.log(p.textContent)); // 可以使用 forEach 遍历 NodeList
    </script>

    * 推荐使用 querySelectorquerySelectorAll,因为它们使用了熟悉的 CSS 选择器语法,更灵活强大。

7.3 操作 DOM 元素

获取到元素后,就可以修改它的属性、内容或样式。

  • 修改元素内容

    • .textContent:获取或设置元素的纯文本内容。
    • .innerHTML:获取或设置元素的 HTML 内容(会解析其中的 HTML 标签)。

    html
    <div id="contentDiv">原始内容</div>
    <script>
    const div = document.getElementById('contentDiv');
    div.textContent = "新的纯文本内容"; // div 的内容变成 "新的纯文本内容"
    div.innerHTML = "新的 <strong>加粗</strong> 内容"; // div 的内容变成 "新的 **加粗** 内容" (加粗会生效)
    </script>

    * 使用 innerHTML 插入来自外部的、不可信的数据是不安全的,可能导致跨站脚本攻击 (XSS),谨慎使用。

  • 修改元素属性

    • .attributeName:直接访问或设置常见的属性(如 id, class, src, href, value 等)。
    • .setAttribute(attributeName, value):设置任意属性的值。
    • .getAttribute(attributeName):获取属性的值。
    • .removeAttribute(attributeName):移除属性。

    “`html
    默认图片


    “`

  • 修改元素样式:使用 .style 属性,后接 CSS 属性名(注意 CSS 属性名在 JS 中需要转为驼峰命名,如 background-color 变为 backgroundColor)。

    ``html
    <div id="styledDiv" style="color: blue;">这段文字是蓝色的</div>
    <script>
    const styledDiv = document.getElementById('styledDiv');
    styledDiv.style.color = "red"; // 将文字颜色改为红色
    styledDiv.style.fontSize = "20px"; // 将字体大小改为 20px
    styledDiv.style.backgroundColor = "yellow"; // 将背景色改为黄色
    </script>
    *
    .style只能修改行内样式。更好的做法是修改元素的 class,然后通过 CSS 控制不同 class 的样式。
    *
    element.classList.add(‘className’):添加类名。
    *
    element.classList.remove(‘className’):移除类名。
    *
    element.classList.toggle(‘className’):如果存在则移除,不存在则添加。
    *
    element.classList.contains(‘className’)`:检查是否存在类名。

    html
    <div id="classDiv" class="active"></div>
    <style>.active { border: 1px solid black; } .highlight { background-color: yellow; }</style>
    <script>
    const classDiv = document.getElementById('classDiv');
    classDiv.classList.remove('active'); // 移除 active 类
    classDiv.classList.add('highlight'); // 添加 highlight 类
    console.log(classDiv.classList.contains('highlight')); // true
    </script>

  • 创建和移除元素

    • document.createElement(tagName):创建一个新的元素节点。
    • parentElement.appendChild(childElement):将一个子元素添加到父元素的末尾。
    • parentElement.removeChild(childElement):从父元素中移除一个子元素。
    • element.remove() (较新方法):移除元素自身。

    “`html

    • 现有列表项


    “`

第八章:事件处理 – 让页面响应用户

网页的交互性很大程度上是通过事件 (Events) 来实现的。事件是用户或浏览器执行的某种动作,例如点击按钮、鼠标移动、键盘按下、页面加载完成等。JavaScript 可以“监听”这些事件,并在事件发生时执行相应的代码。

8.1 什么是事件和事件监听器?

  • 事件:发生在 HTML 元素上的事情。例如:
    • 鼠标事件:click, mouseover, mouseout
    • 键盘事件:keydown, keyup, keypress
    • 表单事件:submit, input, change, focus, blur
    • 文档/窗口事件:load, scroll, resize
  • 事件监听器 (Event Listener):一个函数,当特定事件发生在特定元素上时会被执行。

8.2 添加事件监听器

最推荐使用的方法是 addEventListener()

  • element.addEventListener(event, handler)
    • event:事件名称的字符串(不带 “on”,如 'click' 而不是 'onclick')。
    • handler:一个函数,当事件发生时执行(也称为回调函数)。

“`html

“`

8.3 事件对象 (Event Object)

当事件发生时,浏览器会自动创建一个事件对象,并将其作为参数传递给事件处理函数。这个对象包含了有关事件的详细信息。

javascript
button.addEventListener('click', function(event) { // event 就是事件对象
console.log("事件类型:" + event.type); // 输出 "click"
console.log("触发事件的元素:" + event.target); // 输出触发点击事件的 DOM 元素 (<button id="myButton">...)
console.log("鼠标点击位置 (相对于文档):X=" + event.pageX + ", Y=" + event.pageY); // 对于鼠标事件
});

* 对于不同的事件类型,事件对象包含的属性也不同。了解常用的事件对象属性对于处理复杂交互非常有用。

8.4 阻止默认行为和事件冒泡

  • 阻止默认行为:某些 HTML 元素的事件有默认行为(例如点击链接会跳转、提交表单会刷新页面)。可以使用 event.preventDefault() 来阻止这些默认行为。

    html
    <a href="https://www.example.com" id="myLink">访问示例网站</a>
    <script>
    const link = document.getElementById('myLink');
    link.addEventListener('click', function(event) {
    event.preventDefault(); // 阻止链接的默认跳转行为
    alert("链接的默认行为被阻止了!");
    });
    </script>

  • 事件冒泡 (Event Bubbling):当一个元素上触发某个事件时,该事件会从该元素开始,逐级向上“冒泡”到其父元素、祖先元素,直到文档根部。这意味着父元素也可以捕获到子元素触发的事件。可以使用 event.stopPropagation() 来阻止事件的冒泡。

    “`html


    “`
    * 理解事件冒泡和阻止默认行为是处理复杂页面交互的基础。

第九章:学习资源与进阶之路

恭喜你!走到这里,你已经掌握了 JavaScript 的核心基础。这只是起点,JS 的世界广阔而精彩。接下来的关键是持续学习和大量实践。

9.1 推荐的学习资源

  • MDN Web Docs (Mozilla Developer Network):JavaScript 的官方文档,非常权威、全面且易懂。遇到任何 JS 语法或 Web API 的问题,MDN 都是首选的查阅资料。
  • freeCodeCamp:提供免费的交互式编程课程,包括大量的 JS 练习和项目。
  • Codecademy:提供交互式在线课程,通过动手实践来学习。
  • Udemy / Coursera / edX 等在线教育平台:有许多高质量的付费和免费 JS 课程,可以系统学习。
  • 《JavaScript 高级程序设计》、《深入理解 JavaScript》等经典书籍:系统性学习的深度资料。
  • YouTube / Bilibili 上的技术教程视频:通过观看视频学习和理解概念。
  • GitHub:查找开源项目,学习他人的代码。

9.2 实践的重要性

理论知识只有通过实践才能真正掌握。

  • 动手敲代码:跟着教程敲,然后尝试修改、扩展代码。
  • 解决小问题:尝试用 JS 解决一些实际的小问题,比如:
    • 计算器
    • 待办事项列表 (Todo List)
    • 简单的表单验证
    • 图片轮播
    • 计时器
  • 构建小项目:从简单的静态页面开始,逐步添加 JS 交互功能。
  • 参与开源项目:等你对基础比较熟悉后,可以尝试为一些简单的开源项目贡献代码。

9.3 如何面对错误 (Bug)

编程过程中遇到错误是家常便饭。不要害怕,调试是程序员的基本功。

  • 阅读错误信息:浏览器控制台会显示错误信息,包括错误类型、错误发生的文件和行号。仔细阅读这些信息,它们通常能指引你找到问题所在。
  • 使用 console.log() 调试:在关键位置输出变量的值,检查程序执行流程,定位问题。
  • 使用浏览器开发者工具的断点调试:在代码行号上点击可以设置断点,程序会在该行暂停执行,你可以一步步查看变量的值、执行顺序等,这是最高效的调试方法。

9.4 进阶之路

掌握基础后,JS 的学习和发展方向有很多:

  • 深入 ECMAScript 新特性:ES6+ 带来了许多重要的新特性(如 Promises, Async/Await 处理异步,Classes 实现面向对象等),需要深入学习。
  • 异步编程:JavaScript 处理异步操作(如网络请求、定时器)的方式比较特殊,Promises, Async/Await 是现代 JS 异步编程的核心。
  • 模块化:学习如何组织大型项目,使用 ES Modules (import/export)。
  • 包管理器:了解 npm 或 yarn,如何使用第三方库。
  • 前端框架/库:学习 React, Vue 或 Angular 等流行的前端框架,它们能帮助你更高效地构建复杂的单页面应用 (SPA)。
  • Node.js:学习使用 JavaScript 进行服务器端开发。
  • TypeScript:学习这门 JS 的超集,它引入了静态类型,可以提高大型项目的可维护性。
  • 前端构建工具:了解 Webpack, Vite 等工具,它们用于打包、优化你的前端代码。

结语

学习 JavaScript 是一段充满挑战但也非常有成就感的旅程。从理解变量、数据类型到掌握控制流程、函数、数组、对象,再到利用 DOM 和事件与网页交互,你已经迈出了坚实的第一步。

记住,编程不是一蹴而就的技能。保持好奇心,乐于探索,勤于动手,善于利用资源,积极解决问题。随着你的不断深入,你会发现 JavaScript 的强大之处,并能够创造出令人惊叹的 Web 应用和更多可能性。

祝你在 JavaScript 的学习之路上一切顺利!未来的精彩,等你用代码去创造!


发表评论

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

滚动至顶部