首页 / 知识库 / 0基础入门-阅读资料 / 0基础-前端入门

第三章:JavaScript — 让页面动起来

前两章我们学了 HTML 和 CSS,已经能做出好看的静态页面了。但”静态”两个字说明了一切——页面是死的,用户点什么都没反应。这一章,我们请出前端的第三位主角:JavaScript(简称 JS)。


3.1 JS 是什么

打个比方:

HTML 是骨架(页面的结构),CSS 是皮肤(页面的外观),JS 是大脑和肌肉(页面的行为)。

有了 JS,页面就活了。它能做什么?随便举几个:

  • 点击按钮弹出提示框
  • 输入内容后实时显示字数
  • 提交表单前检查你填的对不对
  • 从服务器拿数据,动态渲染到页面上(比如加载一条新闻列表)
  • 做动画、做游戏、做聊天功能……

基本上你在网页上看到的所有”交互”,背后都是 JS 在干活。

在 HTML 中使用 JS

两种方式:

方式一:直接写在 <script> 标签里

<!DOCTYPE html>
<html>
<head>
  <title>我的第一段 JS</title>
</head>
<body>
  <h1>打开控制台看看</h1>

  <script>
    console.log('Hello JS!')
  </script>
</body>
</html>

方式二:写在外部文件里(推荐)

<!-- index.html -->
<body>
  <h1>打开控制台看看</h1>
  <script src="main.js"></script>
</body>
// main.js
console.log('Hello JS!')

实际开发中基本都用外部文件,代码和页面分离,更好维护。

第一行代码 & 打开控制台

console.log() 是 JS 里的”打印”功能,它会把内容输出到浏览器的控制台

怎么打开控制台?

  1. 用浏览器打开你的 HTML 文件
  2. F12(或右键 → 检查)
  3. 点击上方的 Console(控制台) 标签
  4. 你就能看到 Hello JS!

以后写 JS 的时候,控制台就是你的好朋友,调试全靠它。


3.2 变量与数据类型

变量:给数据起个名字

变量就像一个盒子,你给它贴个标签(名字),然后把东西(数据)放进去。

let age = 20          // 我今年 20 岁
let name = '小明'     // 我叫小明

JS 里声明变量用两个关键字:

  • let — 值可以变的,用 let
  • const — 值不会变的,用 const
let score = 80
score = 95  // ✅ let 声明的变量可以重新赋值

const PI = 3.14159
PI = 3      // ❌ 报错!const 声明的不能改

一句话:能用 const 就用 const,需要改的才用 let。至于 var?忘掉它,那是老写法,容易出 bug。

常用数据类型

类型长什么样说明
字符串"你好"'Hello'用引号包裹的文字
数字423.14直接写数字,不加引号
布尔值true / false表示”是”或”否”
数组[1, 2, 3]一组数据的有序列表(后面详细讲)
对象{ name: "小明" }用键值对描述一个事物(后面详细讲)
const nickname = '前端小白'     // 字符串
const age = 20                  // 数字
const isStudent = true          // 布尔值
const hobbies = ['游戏', '音乐', '编程']  // 数组
const user = { name: '小明', age: 20 }    // 对象

console.log(typeof nickname)  // "string"
console.log(typeof age)       // "number"
console.log(typeof isStudent) // "boolean"

模板字符串:更优雅的拼接方式

以前拼接字符串要用 + 号,又丑又容易出错:

const name = '小明'
const age = 20
console.log('我叫' + name + ',今年' + age + '岁')  // 😩 太难受了

现在用反引号 `${} 就舒服多了:

const name = '小明'
const age = 20
console.log(`我叫${name},今年${age}岁`)  // 😎 清爽!

反引号在键盘左上角,数字 1 的左边那个键(~ 键)。以后拼接字符串一律用模板字符串。


3.3 函数

什么是函数?

函数就是一段可以反复使用的代码。就像一台榨汁机:你放进去水果(参数),它吐出来果汁(返回值)。

普通函数声明

function greet(name) {
  return `你好,${name}!欢迎学习 JS`
}

// 调用函数
console.log(greet('小明'))  // 你好,小明!欢迎学习 JS
console.log(greet('小红'))  // 你好,小红!欢迎学习 JS
  • name参数,调用时传进来的值
  • return返回值,函数执行完吐出来的结果

箭头函数(现代写法)

const greet = (name) => {
  return `你好,${name}!欢迎学习 JS`
}

如果函数体只有一行,还能更简洁:

const greet = (name) => `你好,${name}!欢迎学习 JS`

箭头函数是 ES6 引入的现代写法,后面学 Vue 的时候会大量使用,所以一定要熟悉。

更多示例

// 计算两个数的和
const add = (a, b) => a + b
console.log(add(3, 5))  // 8

// 判断是否成年
const isAdult = (age) => age >= 18
console.log(isAdult(20))  // true
console.log(isAdult(15))  // false

// 生成一句自我介绍
const introduce = (name, hobby) => {
  return `大家好,我是${name},我喜欢${hobby}。`
}
console.log(introduce('小明', '打篮球'))
// 大家好,我是小明,我喜欢打篮球。

3.4 条件判断

程序经常需要做判断:如果怎样就怎样,否则怎样。这就是条件判断。

if / else if / else

const score = 85

if (score >= 90) {
  console.log('优秀')
} else if (score >= 80) {
  console.log('良好')
} else if (score >= 60) {
  console.log('及格')
} else {
  console.log('不及格')
}
// 输出:良好

比较运算符

运算符含义示例
===严格等于3 === 3 → true
!==严格不等于3 !== 5 → true
>大于5 > 3 → true
<小于3 < 5 → true
>=大于等于5 >= 5 → true
<=小于等于3 <= 5 → true

重要:永远用 === 而不是 == == 会做类型转换,容易产生意想不到的结果。比如 "1" == 1true,但 "1" === 1false。用三等号更安全。

逻辑运算符

运算符含义说明
&&与(AND)两边都为 true 才是 true
||或(OR)有一边为 true 就是 true
!非(NOT)取反,true 变 false
const age = 20
const hasTicket = true

// 必须成年 并且 有票 才能进
if (age >= 18 && hasTicket) {
  console.log('欢迎入场')
}

// 是 VIP 或者 有邀请码 就能进
const isVIP = false
const hasInviteCode = true
if (isVIP || hasInviteCode) {
  console.log('欢迎入场')
}

实际示例:成绩等级判定函数

const getGrade = (score) => {
  if (score >= 90) return 'A(优秀)'
  if (score >= 80) return 'B(良好)'
  if (score >= 70) return 'C(中等)'
  if (score >= 60) return 'D(及格)'
  return 'F(不及格)'
}

console.log(getGrade(92))  // A(优秀)
console.log(getGrade(75))  // C(中等)
console.log(getGrade(43))  // F(不及格)

3.5 数组与常用方法

数组就是一组数据排成一排,用方括号 [] 包裹,逗号隔开。

创建和访问

const fruits = ['苹果', '香蕉', '橘子', '葡萄']

// 用下标访问,从 0 开始数
console.log(fruits[0])  // 苹果
console.log(fruits[2])  // 橘子
console.log(fruits.length)  // 4(数组长度)

注意:下标从 0 开始,不是 1。fruits[0] 是第一个元素。

常用方法

push() — 往数组末尾添加元素

const list = ['HTML', 'CSS']
list.push('JavaScript')
console.log(list)  // ['HTML', 'CSS', 'JavaScript']

forEach() — 遍历数组(对每个元素执行操作)

const fruits = ['苹果', '香蕉', '橘子']

fruits.forEach((fruit, index) => {
  console.log(`第${index + 1}个水果是:${fruit}`)
})
// 第1个水果是:苹果
// 第2个水果是:香蕉
// 第3个水果是:橘子

map() — 把每个元素变换成新的,返回新数组

const numbers = [1, 2, 3, 4, 5]
const doubled = numbers.map((n) => n * 2)
console.log(doubled)  // [2, 4, 6, 8, 10]

map() 在 Vue 中渲染列表时非常常用,一定要掌握。

filter() — 筛选出符合条件的元素

const scores = [45, 78, 92, 56, 88, 33, 71]
const passed = scores.filter((s) => s >= 60)
console.log(passed)  // [78, 92, 88, 71]

综合示例

// 学生成绩处理
const students = [
  { name: '小明', score: 92 },
  { name: '小红', score: 56 },
  { name: '小刚', score: 78 },
  { name: '小美', score: 88 },
  { name: '小李', score: 45 },
]

// 筛选出及格的同学
const passedStudents = students.filter((s) => s.score >= 60)

// 打印及格同学的名字和成绩
passedStudents.forEach((s) => {
  console.log(`${s.name}:${s.score}分`)
})
// 小明:92分
// 小刚:78分
// 小美:88分

// 提取所有同学的名字
const names = students.map((s) => s.name)
console.log(names)  // ['小明', '小红', '小刚', '小美', '小李']

3.6 对象

什么是对象?

对象就是用来描述一个”东西”的所有信息。比如描述一个学生:

const student = {
  name: '小明',
  age: 20,
  major: '计算机科学',
  isGraduated: false,
}

对象用花括号 {} 包裹,里面是一对对的 键(key): 值(value)

访问属性

// 方式一:点号(最常用)
console.log(student.name)   // 小明
console.log(student.age)    // 20

// 方式二:方括号(key 是变量或有特殊字符时用)
console.log(student['major'])  // 计算机科学

const key = 'name'
console.log(student[key])  // 小明

对象数组:最常见的数据结构

实际开发中,你从服务器拿到的数据大多长这样——一个数组,里面每个元素是一个对象

const products = [
  { id: 1, name: '手机壳', price: 29.9 },
  { id: 2, name: '数据线', price: 15.0 },
  { id: 3, name: '充电宝', price: 89.0 },
]

// 遍历显示商品信息
products.forEach((p) => {
  console.log(`${p.name} — ¥${p.price}`)
})

后面学 Vue 做项目、调用 API 的时候,打交道最多的就是这种数据结构。一定要熟悉。

解构赋值:快速取出对象中的值

每次都写 student.namestudent.age 太啰嗦了,可以用解构赋值一步到位:

const user = { name: '小明', age: 20, city: '北京' }

// 一行代码取出 name 和 age
const { name, age, city } = user

console.log(name)  // 小明
console.log(age)   // 20
console.log(city)  // 北京

在函数参数中也能用:

const printUser = ({ name, age }) => {
  console.log(`${name},${age}岁`)
}

printUser({ name: '小红', age: 19 })  // 小红,19岁

3.7 DOM 操作 — JS 操控页面的核心

前面我们写的 JS 都在控制台输出,但 JS 真正的威力是操控页面。它是怎么做到的呢?靠的就是 DOM

什么是 DOM?

DOM(Document Object Model) 就是浏览器把 HTML 变成了一棵”对象树”。每个标签都变成了一个对象,JS 可以找到它们、修改它们、删除它们、创建新的。

简单说:HTML 是你写的代码,DOM 是浏览器读完代码后在内存中搭建的结构,JS 通过 DOM 来操控页面。

获取元素

// 获取单个元素(返回第一个匹配的)
const title = document.querySelector('h1')
const btn = document.querySelector('#myBtn')
const box = document.querySelector('.box')

// 获取多个元素(返回一个列表)
const items = document.querySelectorAll('.list-item')

querySelector 里写的就是 CSS 选择器,和你在 CSS 里写的一样。

修改内容

const title = document.querySelector('h1')

// 修改文字内容
title.textContent = '新标题'

// 修改 HTML 内容(可以插入标签)
title.innerHTML = '新<em>标题</em>'

修改样式

const box = document.querySelector('.box')

// 直接改 style(适合改单个属性)
box.style.backgroundColor = '#3498db'
box.style.color = 'white'
box.style.padding = '20px'

// 操作 class(推荐,适合批量样式切换)
box.classList.add('active')      // 添加 class
box.classList.remove('active')   // 移除 class
box.classList.toggle('active')   // 有就移除,没有就添加

监听事件

const btn = document.querySelector('#myBtn')

btn.addEventListener('click', () => {
  console.log('按钮被点击了!')
})

常见事件:click(点击)、input(输入)、submit(提交)、mouseover(鼠标移入)……

创建和添加元素

// 创建一个新的 li 元素
const newItem = document.createElement('li')
newItem.textContent = '新的列表项'

// 把它添加到页面上的 ul 里
const list = document.querySelector('ul')
list.appendChild(newItem)

完整示例一:点击按钮修改文字

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>DOM 示例 1</title>
</head>
<body>
  <h1 id="title">点击下面的按钮试试</h1>
  <button id="btn">点我</button>

  <script>
    const title = document.querySelector('#title')
    const btn = document.querySelector('#btn')

    btn.addEventListener('click', () => {
      title.textContent = 'JS 真的好神奇!🎉'
    })
  </script>
</body>
</html>

完整示例二:点击按钮切换样式

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>DOM 示例 2</title>
  <style>
    .box {
      width: 200px;
      height: 200px;
      background-color: #3498db;
      color: white;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 18px;
      transition: all 0.3s;
      border-radius: 8px;
    }
    .box.active {
      background-color: #e74c3c;
      transform: scale(1.1);
    }
  </style>
</head>
<body>
  <div class="box" id="box">点我变色</div>

  <script>
    const box = document.querySelector('#box')

    box.addEventListener('click', () => {
      box.classList.toggle('active')
    })
  </script>
</body>
</html>

重要提醒: 后面学了 Vue 之后,你就不需要手动操作 DOM 了——Vue 会帮你搞定。但理解 DOM 是必须的基础,因为 Vue 本质上也是在操作 DOM,只是帮你封装好了。


3.8 异步与网络请求

什么是异步?

一个类比:

你点了外卖,不需要站在门口等外卖到了才去做别的事。你可以先去写作业、打游戏,外卖到了手机会通知你。

JS 中的异步也是这个意思。发一个网络请求需要等服务器返回数据,如果”同步”等待,页面就会卡住不动。用”异步”的方式,JS 会先去干别的事,等数据回来了再处理。

async / await 语法

这是目前最简洁好读的异步写法:

// 在函数前加 async,表示这是一个异步函数
// 在需要等待的操作前加 await,表示"等这个操作完成再继续"
const fetchData = async () => {
  const res = await fetch('https://api.example.com/data')
  const data = await res.json()
  console.log(data)
}

fetchData()
  • async 加在函数前面,声明这是个异步函数
  • await 加在异步操作前面,意思是”等它完成,拿到结果再往下走”
  • await 只能在 async 函数里面用

fetch() 发送网络请求

fetch() 是浏览器内置的发请求的函数,不需要装任何库。

const getJoke = async () => {
  // 发送 GET 请求
  const res = await fetch('https://official-joke-api.appspot.com/random_joke')
  // 把响应转成 JSON 对象
  const joke = await res.json()

  console.log(`问:${joke.setup}`)
  console.log(`答:${joke.punchline}`)
}

getJoke()

错误处理:try / catch

网络请求可能失败(断网、服务器挂了……),所以最好包一层 try/catch

const getData = async () => {
  try {
    const res = await fetch('https://api.example.com/users')
    const users = await res.json()
    console.log('获取到的用户数据:', users)
  } catch (error) {
    console.log('请求失败了:', error.message)
  }
}

getData()
  • try 里放正常逻辑
  • 如果出错了,自动跳到 catch 里处理

这一节的 async/awaitfetch 是为下一章学 Vue 调用 API 做铺垫。到时候你会在 Vue 组件里用类似的写法从后端获取数据,现在先把语法搞熟就行。


3.9 实战练习:待办事项

学了这么多,来做个小项目吧!我们用纯 HTML + CSS + JS 做一个待办事项功能:

  • 在输入框中输入内容,点击按钮添加到列表
  • 点击列表项可以标记为”已完成”(加删除线)

完整代码

把下面的代码保存成 todo.html,用浏览器打开就能玩:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>待办事项</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: -apple-system, 'Microsoft YaHei', sans-serif;
      background-color: #f0f2f5;
      display: flex;
      justify-content: center;
      padding-top: 60px;
    }

    .todo-app {
      background: white;
      padding: 30px;
      border-radius: 12px;
      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
      width: 400px;
    }

    .todo-app h1 {
      text-align: center;
      margin-bottom: 20px;
      color: #333;
      font-size: 24px;
    }

    .input-area {
      display: flex;
      gap: 10px;
      margin-bottom: 20px;
    }

    .input-area input {
      flex: 1;
      padding: 10px 14px;
      border: 2px solid #ddd;
      border-radius: 8px;
      font-size: 15px;
      outline: none;
      transition: border-color 0.2s;
    }

    .input-area input:focus {
      border-color: #3498db;
    }

    .input-area button {
      padding: 10px 20px;
      background-color: #3498db;
      color: white;
      border: none;
      border-radius: 8px;
      font-size: 15px;
      cursor: pointer;
      transition: background-color 0.2s;
    }

    .input-area button:hover {
      background-color: #2980b9;
    }

    .todo-list {
      list-style: none;
    }

    .todo-list li {
      padding: 12px 14px;
      border-bottom: 1px solid #eee;
      cursor: pointer;
      font-size: 15px;
      color: #333;
      transition: all 0.2s;
    }

    .todo-list li:hover {
      background-color: #f8f9fa;
    }

    .todo-list li.done {
      text-decoration: line-through;
      color: #aaa;
    }

    .empty-tip {
      text-align: center;
      color: #bbb;
      padding: 20px;
      font-size: 14px;
    }
  </style>
</head>
<body>
  <div class="todo-app">
    <h1>📝 待办事项</h1>

    <div class="input-area">
      <input type="text" id="todoInput" placeholder="输入待办事项...">
      <button id="addBtn">添加</button>
    </div>

    <ul class="todo-list" id="todoList">
      <!-- 待办事项会被 JS 添加到这里 -->
    </ul>
    <p class="empty-tip" id="emptyTip">还没有待办事项,快添加一个吧!</p>
  </div>

  <script>
    // 获取页面元素
    const input = document.querySelector('#todoInput')
    const addBtn = document.querySelector('#addBtn')
    const todoList = document.querySelector('#todoList')
    const emptyTip = document.querySelector('#emptyTip')

    // 更新空提示的显示状态
    const updateEmptyTip = () => {
      if (todoList.children.length === 0) {
        emptyTip.style.display = 'block'
      } else {
        emptyTip.style.display = 'none'
      }
    }

    // 添加待办事项
    const addTodo = () => {
      const text = input.value.trim()

      // 输入为空就不添加
      if (text === '') return

      // 创建新的列表项
      const li = document.createElement('li')
      li.textContent = text

      // 点击列表项,切换"完成"状态
      li.addEventListener('click', () => {
        li.classList.toggle('done')
      })

      // 添加到列表中
      todoList.appendChild(li)

      // 清空输入框,方便继续输入
      input.value = ''
      input.focus()

      // 更新空提示
      updateEmptyTip()
    }

    // 点击按钮添加
    addBtn.addEventListener('click', addTodo)

    // 按回车也能添加
    input.addEventListener('keydown', (e) => {
      if (e.key === 'Enter') {
        addTodo()
      }
    })
  </script>
</body>
</html>

代码解读

  1. 获取元素:用 querySelector 获取输入框、按钮、列表等 DOM 元素
  2. addTodo 函数:读取输入框内容 → 创建 <li> 元素 → 绑定点击事件 → 添加到列表
  3. 点击切换完成:给每个 <li> 添加 click 事件,点击时 toggle 一个 done class,CSS 中定义了 .done 有删除线效果
  4. 按回车添加:监听 keydown 事件,判断按的是不是 Enter 键

动手扩展

这个小项目有很多可以玩的地方,试试看:

  • 给每个待办事项加一个”删除”按钮
  • 在顶部显示”共 X 项,已完成 X 项”
  • localStorage 保存数据,刷新页面后不会丢失(可以搜一下怎么用)
  • 给已完成和未完成的事项加上不同的背景色

恭喜你! 到这里,你已经掌握了 JavaScript 的核心基础。我们来回顾一下这一章学了什么:

  • 变量和数据类型letconst、字符串、数字、布尔、数组、对象
  • 函数:普通函数和箭头函数
  • 条件判断if/else、比较运算符、逻辑运算符
  • 数组方法forEachmapfilter
  • 对象:键值对、解构赋值、对象数组
  • DOM 操作:获取元素、修改内容和样式、监听事件
  • 异步请求async/awaitfetch

下一章我们就要进入 Vue.js 的世界了。有了这一章的 JS 基础,你会发现 Vue 其实很好上手——它把 DOM 操作、数据绑定、事件处理都封装好了,让你用更少的代码做出更多的事情。加油!