04.JavaScript基础

1. JavaScript是什么?为什么需要它?

1.1 从"静态"到"动态":HTML、CSS与JavaScript的关系

还记得我们之前学的HTML和CSS吗?

  • HTML = 网页的"骨架"(结构)
  • CSS = 网页的"皮肤"(样式)
  • JavaScript = 网页的"大脑"(行为)

实际例子

只有HTML+CSS的网页(静态,不能交互):

1
2
<button>点击我</button>
<!-- 点击按钮,什么都不会发生 -->

加上JavaScript后的网页(动态,可以交互):

1
2
3
4
5
6
<button id="myButton">点击我</button>
<script>
document.getElementById('myButton').addEventListener('click', function() {
alert('按钮被点击了!');
});
</script>

💡 关键理解
HTML负责"内容是什么",CSS负责"内容长什么样",JavaScript负责"内容能做什么"。


1.2 JavaScript的诞生

1995年,网景公司(Netscape)的Brendan Eich在10天内创造了JavaScript

时间 事件 意义
1995年5月 JavaScript诞生 最初叫"LiveScript",后来改名"JavaScript"
1997年 ECMAScript标准发布 统一JavaScript标准
2009年 Node.js诞生 JavaScript可以运行在服务器端
2015年 ES6发布 现代JavaScript语法,功能大幅增强

💡 历史趣闻
JavaScript和Java完全不是同一种语言(就像"汽车"和"汽车旅馆")。


1.3 为什么JavaScript对现代Web开发至关重要?

重要性 说明 实际案例
交互功能 让网页"活起来",响应用户操作 点击按钮弹出提示、表单验证
数据操作 处理用户输入、发送请求、更新页面 搜索框实时提示、购物车添加商品
全栈开发 前端和后端都能用JavaScript Node.js做后端、React/Vue做前端

2. DOM操作实践:让网页"听话"的魔法

2.1 什么是DOM?

DOM = Document Object Model(文档对象模型)

  • 作用:把HTML文档转换成JavaScript可以操作的对象
  • 本质:浏览器在内存中创建的HTML文档的"树形结构"

💡 记忆技巧
DOM = 网页的"遥控器",JavaScript通过DOM控制网页的每一个元素。


2.2 如何获取DOM元素?

2.2.1 核心方法

方法 返回类型 适用场景
getElementById('id') 单个元素 获取唯一元素
querySelector('选择器') 单个元素 推荐! 灵活选择单个元素
querySelectorAll('选择器') 数组 推荐! 灵活选择多个元素

实际例子

1
2
3
4
5
6
7
8
<h1 id="title">我的标题</h1>
<p class="text">段落1</p>
<p class="text">段落2</p>
<script>
const title = document.getElementById('title');
const text = document.querySelector('.text'); // 获取第一个
const texts = document.querySelectorAll('.text'); // 获取所有
</script>

2.3 如何修改DOM元素?

2.3.1 修改内容

  • textContent - 修改文本内容(推荐,更安全)
  • innerHTML - 修改HTML内容(注意XSS攻击)

实际例子

1
2
3
4
5
<p id="text">原始内容</p>
<script>
const text = document.getElementById('text');
text.textContent = '新内容'; // 修改文本
</script>

2.3.2 修改样式

  • style.属性 - 直接修改样式
  • classList - 添加/删除CSS类(推荐)

实际例子

1
2
3
4
5
6
<p id="text">这是一段文字</p>
<script>
const text = document.getElementById('text');
text.style.color = 'red'; // 直接修改样式
text.classList.add('highlight'); // 添加CSS类(推荐)
</script>


2.4 如何创建和删除DOM元素?

创建元素document.createElement('标签名')

删除元素元素.remove()

实际例子

1
2
3
4
5
6
7
8
9
10
11
12
<div id="container"></div>
<script>
// 创建新元素
const newP = document.createElement('p');
newP.textContent = '新段落';

// 添加到页面
document.getElementById('container').appendChild(newP);

// 删除元素
// newP.remove();
</script>


2.5 实战案例:制作一个待办事项列表

需求:输入框输入待办事项,点击添加按钮后显示在列表中,每个事项有删除按钮。

HTML结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>待办事项列表</title>
<style>
body { font-family: '微软雅黑', Arial, sans-serif; max-width: 600px; margin: 50px auto; }
.input-group { display: flex; gap: 10px; margin-bottom: 20px; }
#todoInput { flex: 1; padding: 10px; }
.todo-item { display: flex; justify-content: space-between; padding: 10px; margin-bottom: 10px; background: #f0f0f0; }
.delete-btn { background: #ff4444; color: white; border: none; padding: 5px 10px; cursor: pointer; }
</style>
</head>
<body>
<h1>📝 待办事项列表</h1>
<div class="input-group">
<input type="text" id="todoInput" placeholder="输入待办事项...">
<button onclick="addTodo()">添加</button>
</div>
<ul id="todoList"></ul>
<script>
function addTodo() {
const input = document.getElementById('todoInput');
const todoText = input.value.trim();

if (todoText === '') {
alert('请输入待办事项!');
return;
}

const li = document.createElement('li');
li.className = 'todo-item';

const textSpan = document.createElement('span');
textSpan.textContent = todoText;

const deleteBtn = document.createElement('button');
deleteBtn.textContent = '删除';
deleteBtn.className = 'delete-btn';
deleteBtn.onclick = function() {
li.remove();
};

li.appendChild(textSpan);
li.appendChild(deleteBtn);

document.getElementById('todoList').appendChild(li);
input.value = '';
}

// 按回车键也可以添加
document.getElementById('todoInput').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
addTodo();
}
});
</script>
</body>
</html>


3. 事件监听机制:让网页"听懂"你的操作

3.1 什么是事件?

事件 = 用户在网页上的操作(点击、输入、滚动等)

事件监听 = JavaScript"监听"这些操作,然后执行相应的代码

实际例子

1
2
3
4
5
6
<button id="myButton">点击我</button>
<script>
document.getElementById('myButton').addEventListener('click', function() {
alert('按钮被点击了!');
});
</script>


3.2 常用事件类型

事件类型 触发时机 示例
click 鼠标点击 点击按钮、链接
mouseenter 鼠标移入 鼠标移到元素上
mouseleave 鼠标移出 鼠标离开元素
keyup 松开键盘 在输入框中输入
submit 提交表单 点击提交按钮
input 输入内容 在输入框中输入

3.3 如何添加事件监听?

方法:addEventListener(推荐!)

语法元素.addEventListener('事件类型', 处理函数)

实际例子

1
2
3
4
5
6
7
<button id="btn">点击我</button>
<script>
const btn = document.getElementById('btn');
btn.addEventListener('click', function() {
alert('按钮被点击了!');
});
</script>

🌟 为什么推荐addEventListener

  • 可以给同一个元素添加多个相同类型的事件监听
  • 代码更清晰、易维护

3.4 事件对象

事件对象 = 包含事件详细信息的对象(如鼠标位置、按下的键、目标元素等)

实际例子

1
2
3
4
5
6
7
8
9
10
<button id="btn">点击我</button>
<script>
const btn = document.getElementById('btn');
btn.addEventListener('click', function(e) {
// e 就是事件对象
console.log('事件类型:', e.type); // click
console.log('目标元素:', e.target); // <button>
console.log('鼠标X坐标:', e.clientX);
});
</script>

常用属性

  • e.type - 事件类型
  • e.target - 触发事件的元素
  • e.key - 按下的键(键盘事件)
  • e.preventDefault() - 阻止默认行为(如阻止表单提交)

3.5 事件冒泡:理解事件的传播机制

3.5.1 什么是事件冒泡?

事件冒泡 = 事件从最内层元素向外层元素传播的过程

示意图

1
2
3
4
5
6
7
用户点击按钮

[button] ← 事件在这里触发
↓ 事件冒泡
[div] ← 事件传播到这里
↓ 事件冒泡
[body] ← 事件传播到这里

实际例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<div id="outer" style="padding: 50px; background: blue;">
<div id="inner" style="padding: 50px; background: red;">
<button id="btn">点击我</button>
</div>
</div>
<script>
const outer = document.getElementById('outer');
const inner = document.getElementById('inner');
const btn = document.getElementById('btn');

btn.addEventListener('click', function() {
alert('按钮被点击了!');
});

inner.addEventListener('click', function() {
alert('内层div被点击了!');
});

outer.addEventListener('click', function() {
alert('外层div被点击了!');
});
</script>

效果:点击按钮时,会依次弹出三个提示框(从内到外)。

💡 关键理解
事件冒泡让外层元素也能"感知"到内层元素的事件。这在某些场景下很有用(如事件委托),但有时也需要阻止冒泡。

3.5.2 如何阻止事件冒泡?

语法e.stopPropagation()

实际例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div id="outer" style="padding: 50px; background: blue;">
<button id="btn">点击我</button>
</div>
<script>
const outer = document.getElementById('outer');
const btn = document.getElementById('btn');

btn.addEventListener('click', function(e) {
e.stopPropagation(); // 阻止事件冒泡
alert('按钮被点击了!');
});

outer.addEventListener('click', function() {
alert('外层div被点击了!');
});
</script>

效果:点击按钮时,只弹出"按钮被点击了!",不会触发外层div的事件。


4. 表单数据获取

4.1 如何获取表单数据?

方法1:通过value属性(最常用)

实际例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<form id="myForm">
<input type="text" id="username" placeholder="用户名">
<input type="password" id="password" placeholder="密码">
<button type="submit">提交</button>
</form>
<script>
const form = document.getElementById('myForm');

form.addEventListener('submit', function(e) {
e.preventDefault(); // 阻止表单默认提交

const username = document.getElementById('username').value;
const password = document.getElementById('password').value;

console.log('用户名:', username);
console.log('密码:', password);
});
</script>

方法2:通过FormData对象(推荐)

实际例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<form id="myForm">
<input type="text" name="username" placeholder="用户名">
<input type="password" name="password" placeholder="密码">
<button type="submit">提交</button>
</form>
<script>
const form = document.getElementById('myForm');

form.addEventListener('submit', function(e) {
e.preventDefault();

const formData = new FormData(form);
const username = formData.get('username');
const password = formData.get('password');

console.log('用户名:', username);
console.log('密码:', password);
});
</script>

💡 注意:使用FormData时,表单元素需要有name属性。


4.2 常用表单元素的数据获取

元素类型 获取方法 示例
input[type="text"] .value input.value
input[type="password"] .value input.value
textarea .value textarea.value
select .value select.value
input[type="checkbox"] .checked checkbox.checked
input[type="radio"] .checked radio.checked

实际例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<input type="text" id="textInput">
<textarea id="textarea"></textarea>
<select id="select">
<option value="1">选项1</option>
<option value="2">选项2</option>
</select>
<input type="checkbox" id="checkbox">
<input type="radio" name="gender" value="male" id="male">
<input type="radio" name="gender" value="female" id="female">

<script>
const textInput = document.getElementById('textInput').value;
const textarea = document.getElementById('textarea').value;
const select = document.getElementById('select').value;
const checkbox = document.getElementById('checkbox').checked;

// 获取选中的radio
const gender = document.querySelector('input[name="gender"]:checked').value;
</script>


5. AI实战:使用AI实现表单验证

5.1 任务描述

目标:使用AI工具生成一个带表单验证的用户注册页面

功能要求

  • 用户名:必填,长度3-20个字符
  • 密码:必填,长度至少6个字符
  • 确认密码:必须与密码一致
  • 邮箱:必填,格式正确
  • 提交时进行验证,显示错误提示

5.2 第一步:设计Prompt

Prompt示例

1
2
3
4
5
6
7
8
9
10
用HTML、CSS、JavaScript创建一个用户注册表单,要求:
1. 包含用户名、密码、确认密码、邮箱四个输入框
2. 实现表单验证:
- 用户名:必填,3-20个字符
- 密码:必填,至少6个字符
- 确认密码:必须与密码一致
- 邮箱:必填,格式验证
3. 验证失败时在输入框下方显示红色错误提示
4. 使用addEventListener监听表单提交事件
5. 代码注释清晰,样式简洁美观


5.3 AI生成的代码(示例)

HTML结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户注册</title>
<style>
body {
font-family: '微软雅黑', Arial, sans-serif;
max-width: 500px;
margin: 50px auto;
padding: 20px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
.error {
color: red;
font-size: 12px;
margin-top: 5px;
}
button {
width: 100%;
padding: 12px;
background-color: #3498db;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #2980b9;
}
</style>
</head>
<body>
<h1>用户注册</h1>
<form id="registerForm">
<div class="form-group">
<label for="username">用户名:</label>
<input type="text" id="username" name="username">
<div class="error" id="usernameError"></div>
</div>

<div class="form-group">
<label for="password">密码:</label>
<input type="password" id="password" name="password">
<div class="error" id="passwordError"></div>
</div>

<div class="form-group">
<label for="confirmPassword">确认密码:</label>
<input type="password" id="confirmPassword" name="confirmPassword">
<div class="error" id="confirmPasswordError"></div>
</div>

<div class="form-group">
<label for="email">邮箱:</label>
<input type="email" id="email" name="email">
<div class="error" id="emailError"></div>
</div>

<button type="submit">注册</button>
</form>

<script>
// JavaScript代码在下面
</script>
</body>
</html>

JavaScript验证代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
const form = document.getElementById('registerForm');

form.addEventListener('submit', function(e) {
e.preventDefault(); // 阻止表单默认提交

// 清除之前的错误提示
clearErrors();

// 获取表单数据
const username = document.getElementById('username').value.trim();
const password = document.getElementById('password').value;
const confirmPassword = document.getElementById('confirmPassword').value;
const email = document.getElementById('email').value.trim();

let isValid = true;

// 验证用户名
if (username === '') {
showError('usernameError', '用户名不能为空');
isValid = false;
} else if (username.length < 3 || username.length > 20) {
showError('usernameError', '用户名长度必须在3-20个字符之间');
isValid = false;
}

// 验证密码
if (password === '') {
showError('passwordError', '密码不能为空');
isValid = false;
} else if (password.length < 6) {
showError('passwordError', '密码长度至少6个字符');
isValid = false;
}

// 验证确认密码
if (confirmPassword === '') {
showError('confirmPasswordError', '请确认密码');
isValid = false;
} else if (password !== confirmPassword) {
showError('confirmPasswordError', '两次输入的密码不一致');
isValid = false;
}

// 验证邮箱
if (email === '') {
showError('emailError', '邮箱不能为空');
isValid = false;
} else if (!isValidEmail(email)) {
showError('emailError', '邮箱格式不正确');
isValid = false;
}

// 如果验证通过,提交表单
if (isValid) {
alert('注册成功!');
// 这里可以发送数据到服务器
}
});

// 显示错误提示
function showError(errorId, message) {
const errorElement = document.getElementById(errorId);
errorElement.textContent = message;
}

// 清除所有错误提示
function clearErrors() {
const errorElements = document.querySelectorAll('.error');
errorElements.forEach(function(el) {
el.textContent = '';
});
}

// 验证邮箱格式
function isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}


5.4 代码解析

核心思路

  1. 监听表单的submit事件
  2. 使用e.preventDefault()阻止默认提交
  3. 获取各个输入框的值
  4. 逐个验证,显示错误提示
  5. 全部验证通过后,执行提交操作

关键点

  • 使用addEventListener监听表单提交
  • 使用trim()去除首尾空格
  • 使用正则表达式验证邮箱格式
  • 错误提示显示在输入框下方

💡 提示
这个例子展示了如何用AI快速生成表单验证代码。你可以在此基础上修改验证规则,添加更多功能。


6. 选讲:ES6与TypeScript

6.1 ES6是什么?

ES6 = ECMAScript 6(2015年发布的JavaScript标准)

ES6带来的重要改进

特性 说明 示例
let/const 块级作用域变量声明 let x = 1; const y = 2;
箭头函数 更简洁的函数写法 () => {}
模板字符串 支持变量插值的字符串 `Hello ${name}`
解构赋值 从数组/对象中提取值 const {name, age} = user;
Promise 异步编程解决方案 处理异步操作

6.2 ES6常用特性(快速了解)

6.2.1 let和const

传统方式(ES5)

1
var x = 1;  // 函数作用域

ES6方式

1
2
let x = 1;      // 块级作用域,可以重新赋值
const y = 2; // 块级作用域,不能重新赋值(常量)

实际例子

1
2
3
4
5
6
7
// 使用let
let count = 0;
count = 1; // ✅ 可以重新赋值

// 使用const
const PI = 3.14;
PI = 3.14159; // ❌ 报错!const不能重新赋值

💡 建议
优先使用const,需要重新赋值时再用let,避免使用var


6.2.2 箭头函数

生活类比

想象你要写一个"计算器":

  • 传统函数 = 用完整的句子说:"我要做一个加法函数,它接收两个数字,然后返回它们的和"
  • 箭头函数 = 用简短的句子说:"两个数字相加"(更简洁,意思一样)

传统方式(ES5)

1
2
3
function add(a, b) {
return a + b;
}

ES6箭头函数

1
2
3
4
5
6
7
// 完整写法
const add = (a, b) => {
return a + b;
};

// 简洁写法(只有一行代码时,可以省略大括号和return)
const add = (a, b) => a + b;

实际例子对比

1
2
3
4
5
6
7
8
9
// 传统函数
document.getElementById('btn').addEventListener('click', function() {
alert('按钮被点击了!');
});

// 箭头函数(更简洁)
document.getElementById('btn').addEventListener('click', () => {
alert('按钮被点击了!');
});

箭头函数的好处

好处 说明 实际效果
代码更简洁 写法更短,少写很多字 从5行代码变成1行代码
更易读 一眼就能看出"这是做什么的" 代码更清晰,维护更容易
自动绑定this 不会改变this的指向(高级特性) 在某些场景下更安全

什么时候用箭头函数?

推荐使用箭头函数

  • 简单的函数(如事件处理、数组方法)
  • 不需要this的场景

不推荐用箭头函数

  • 需要this指向特定对象的场景(如对象方法)
  • 需要作为构造函数使用的函数

更多例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 例子1:数组方法(推荐用箭头函数)
const numbers = [1, 2, 3, 4, 5];

// 传统写法
const doubled = numbers.map(function(num) {
return num * 2;
});

// 箭头函数写法(更简洁)
const doubled = numbers.map(num => num * 2);

// 例子2:事件处理(推荐用箭头函数)
button.addEventListener('click', () => {
console.log('按钮被点击了');
});

// 例子3:对象方法(不推荐用箭头函数)
const person = {
name: '张三',
// ❌ 不推荐:箭头函数的this不会指向person
greet: () => {
console.log('你好,我是' + this.name); // this.name会是undefined
},
// ✅ 推荐:传统函数
greet2: function() {
console.log('你好,我是' + this.name); // 正确显示"张三"
}
};

💡 记忆技巧
箭头函数就像"简化版"的函数,写起来更短、更简洁。
大部分情况下用箭头函数都很好,但记住:对象的方法不要用箭头函数


6.2.3 模板字符串

传统方式(ES5)

1
2
const name = '张三';
const message = '你好,' + name + '!';

ES6模板字符串

1
2
const name = '张三';
const message = `你好,${name}!`; // 使用反引号和${}

实际例子

1
2
3
4
const username = 'admin';
const age = 20;
const info = `用户名:${username},年龄:${age}`;
// 输出:用户名:admin,年龄:20


6.3 TypeScript是什么?

TypeScript = JavaScript + 类型系统

  • 本质:TypeScript是JavaScript的超集,编译后变成JavaScript
  • 优势:提供类型检查,减少错误,提高代码质量
  • 适用场景:大型项目、团队协作

对比

特性 JavaScript TypeScript
类型检查 运行时检查 编译时检查
错误发现 运行时才发现 写代码时就能发现
代码提示 有限 更智能

实际例子

JavaScript

1
2
3
4
5
function add(a, b) {
return a + b;
}

add(1, '2'); // 返回 '12'(字符串拼接,可能不是你想要的结果)

TypeScript

1
2
3
4
5
6
function add(a: number, b: number): number {
return a + b;
}

add(1, '2'); // ❌ 编译时报错!类型不匹配
add(1, 2); // ✅ 正确


6.4 TypeScript基础语法

6.4.1 类型注解

基本类型

1
2
3
let name: string = '张三';
let age: number = 20;
let isActive: boolean = true;

函数类型

1
2
3
function greet(name: string): string {
return `你好,${name}!`;
}

实际例子

1
2
3
4
5
6
7
// 定义函数参数和返回值类型
function calculateArea(width: number, height: number): number {
return width * height;
}

const area = calculateArea(10, 20); // ✅ 正确
const area2 = calculateArea('10', 20); // ❌ 编译错误


6.4.2 接口(Interface)

作用:定义对象的结构

实际例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 定义用户接口
interface User {
name: string;
age: number;
email: string;
}

// 使用接口
function createUser(user: User): void {
console.log(`创建用户:${user.name}`);
}

createUser({
name: '张三',
age: 20,
email: 'zhangsan@example.com'
}); // ✅ 正确

createUser({
name: '李四'
// ❌ 编译错误:缺少age和email
});


6.5 为什么学习ES6和TypeScript?

原因 说明
现代开发标准 ES6是现代JavaScript的基础,必须掌握
提高代码质量 TypeScript的类型检查能减少bug
团队协作 类型定义让代码更易理解和维护
就业优势 很多公司要求掌握ES6和TypeScript

💡 学习建议

  • 先掌握ES6:这是现代JavaScript的基础,必须学会

  • 再学TypeScript:在掌握JavaScript基础后,再学习TypeScript会更容易

  • 循序渐进:不要一开始就学TypeScript,先打好JavaScript基础


本章总结

通过本章的学习,你已经掌握了:

JavaScript基础

  • JavaScript的作用和重要性
  • DOM操作的核心方法
  • 事件监听机制
  • 表单数据获取

实战技能

  • 制作待办事项列表
  • 实现表单验证功能
  • 使用AI生成代码

进阶知识(选讲):

  • ES6常用特性
  • TypeScript基础概念

🌟 恭喜你!
你已经掌握了JavaScript的核心技能!
这些知识将帮助你:

  • 制作交互式网页

  • 实现表单验证

  • 提升开发效率

继续练习,继续探索,Web开发的世界等着你! 🚀