补充课05:JavaScript和TypeScript

JavaScript 让网页”动起来”,TypeScript 让 JavaScript”更可靠”。

在之前的课程中,你看到 Next.js 项目里全是 .tsx.ts 文件。它们是什么?和 JavaScript 有什么关系?这一课,我们一次性讲清楚。


1. JavaScript 是什么?

JavaScript(简称 JS) 是网页的”行为”语言。HTML 负责结构,CSS 负责样式,JavaScript 负责交互。

graph LR
    A[网页三要素] --> B[HTML<br/>结构]
    A --> C[CSS<br/>样式]
    A --> D[JavaScript<br/>行为]
    
    B --> E["<h1>标题</h1>"]
    C --> F["color: red;"]
    D --> G["点击后弹出提示"]
语言角色比喻
HTML结构房子的骨架和墙壁
CSS样式房子的装修和配色
JavaScript行为房子的灯光、门锁、智能设备

没有 JavaScript 的网页是”死的”——点击按钮没反应,数据不会刷新,动画不会动。


2. 变量:let 和 const

在 JavaScript 中,变量用来存储数据。

// const —— 常量,一旦赋值不能改(推荐优先使用)
const name = "小明";
// name = "小红"; // 报错!const 不能重新赋值
 
// let —— 变量,可以重新赋值
let age = 18;
age = 19; // OK
 
// var —— 旧式变量声明(不要用)
var oldWay = "过时了"; // 不要用 var!

用 const 还是 let?

情况用哪个举例
值不会变const用户ID、API地址、配置
值会变let计数器、循环变量、累加器
任何情况var不要用

TIP

最佳实践:默认用 const,只有当确定需要重新赋值时才用 let。 99% 的场景用 const 就够了。


3. 数据类型

JavaScript 的数据类型其实很简单,记住常用的几种就行:

// 字符串(String)—— 文本
const name = "小明";
const greeting = `你好,${name}!`; // 模板字符串(推荐)
 
// 数字(Number)—— 整数和小数
const count = 42;
const price = 19.99;
 
// 布尔值(Boolean)—— 是/否
const isActive = true;
const isAdmin = false;
 
// 数组(Array)—— 列表
const fruits = ["苹果", "香蕉", "橘子"];
const numbers = [1, 2, 3, 4, 5];
 
// 对象(Object)—— 键值对集合
const user = {
  name: "小明",
  age: 18,
  isActive: true
};

template string 模板字符串

用反引号 ` 包裹,可以用 ${} 嵌入变量:

// 旧方式(字符串拼接)
const msg1 = "你好," + name + ",你今年" + age + "岁了";
 
// 新方式(模板字符串)—— 推荐!
const msg2 = `你好,${name},你今年${age}岁了`;

4. 函数

函数是”可重复使用的代码块”。

传统函数

function greet(name) {
  return `你好,${name}!`;
}
 
const result = greet("小明");
console.log(result); // "你好,小明!"

箭头函数(推荐)

// 箭头函数 —— 更简洁
const greet = (name) => {
  return `你好,${name}!`;
};
 
// 如果只有一行,可以省略 return 和花括号
const greet = (name) => `你好,${name}!`;
 
// 如果只有一个参数,可以省略括号
const double = n => n * 2;

函数参数默认值

const greet = (name = "朋友") => `你好,${name}!`;
 
greet();      // "你好,朋友!"
greet("小红"); // "你好,小红!"

对比

特性传统 function箭头函数
语法冗长简洁
this 指向动态继承外层
适用场景构造函数、方法回调、表达式
现代项目使用频率较少极多

TIP

在 AI 编程中,你几乎不需要手写函数——让 AI 帮你写。但你需要能看懂。


5. 条件判断

if / else

const age = 18;
 
if (age >= 18) {
  console.log("已成年");
} else {
  console.log("未成年");
}
 
// 多条件
const score = 85;
if (score >= 90) {
  console.log("优秀");
} else if (score >= 60) {
  console.log("及格");
} else {
  console.log("不及格");
}

三元运算符(简写 if/else)

const status = age >= 18 ? "成年" : "未成年";
// 相当于:
// let status;
// if (age >= 18) { status = "成年"; } else { status = "未成年"; }

switch

const day = "周一";
 
switch (day) {
  case "周一":
    console.log("开工!");
    break;
  case "周五":
    console.log("快周末了!");
    break;
  case "周六":
  case "周日":
    console.log("放假!");
    break;
  default:
    console.log("普通工作日");
}

6. 循环

for 循环

const fruits = ["苹果", "香蕉", "橘子"];
 
// 传统 for
for (let i = 0; i < fruits.length; i++) {
  console.log(fruits[i]);
}
 
// for...of(推荐)
for (const fruit of fruits) {
  console.log(fruit);
}

forEach(数组专用)

fruits.forEach((fruit, index) => {
  console.log(`${index}: ${fruit}`);
});

map(最常用!在 React 中)

const upperFruits = fruits.map(fruit => fruit + "!");
// ["苹果!", "香蕉!", "橘子!"]
graph LR
    A["['苹果', '香蕉', '橘子']"] --> B[.map]
    B --> C["['苹果!', '香蕉!', '橘子!']"]
    
    A2["['苹果', '香蕉', '橘子']"] --> B2[.filter]
    B2 --> C2["['苹果']"]

TIP

在 React/Next.js 中,map 是使用频率最高的数组方法,用于把数组渲染成 UI 列表。


7. DOM 操作

JavaScript 可以”操控”网页上的元素。

DOM = Document Object Model(文档对象模型),就是浏览器将 HTML 转换成的”对象树”。

选中元素

// 通过 ID 选中
const title = document.getElementById("my-title");
 
// 通过 CSS 选择器选中(最常用)
const button = document.querySelector(".submit-btn");
const allButtons = document.querySelectorAll("button");

修改内容

const title = document.querySelector("h1");
title.textContent = "新标题";         // 改文字
title.innerHTML = "<em>新标题</em>";  // 改 HTML
title.style.color = "red";            // 改样式
title.classList.add("active");        // 添加 class

添加事件

const button = document.querySelector("button");
 
button.addEventListener("click", () => {
  alert("你点击了按钮!");
});

完整示例

<button id="myBtn">点我</button>
<p id="message">原始消息</p>
 
<script>
  const btn = document.querySelector("#myBtn");
  const msg = document.querySelector("#message");
 
  btn.addEventListener("click", () => {
    msg.textContent = "消息已被更新!";
    msg.style.color = "blue";
  });
</script>

NOTE

在 Next.js/React 中,你很少直接操作 DOM(不用 document.querySelector)。React 用声明式的方式管理 UI。但理解 DOM 操作有助于理解”前端在做什么”。


8. TypeScript 是什么?

TypeScript(简称 TS) 是”带类型的 JavaScript”——它是 JavaScript 的超集。

graph TD
    A[TypeScript] --> B[JavaScript 全部语法]
    A --> C[类型系统]
    
    B --> D[.js 文件都能跑]
    C --> E[变量、参数、返回值都有类型]
    
    E --> F[提前发现错误]
    E --> G[编辑器智能提示]
    E --> H[代码自文档化]

类型注解

// 变量类型
const name: string = "小明";
const age: number = 18;
const isActive: boolean = true;
 
// 数组类型
const fruits: string[] = ["苹果", "香蕉"];
 
// 函数参数和返回值
function greet(name: string): string {
  return `你好,${name}`;
}
 
// 箭头函数
const add = (a: number, b: number): number => a + b;

interface(接口)

// 定义"用户"这个对象的形状
interface User {
  id: number;
  name: string;
  email: string;
  age?: number;    // ? 表示可选
  isActive: boolean;
}
 
// 使用接口
const user: User = {
  id: 1,
  name: "小明",
  email: "xiaoming@example.com",
  isActive: true
};
 
// 函数参数使用接口
function formatUser(user: User): string {
  return `${user.name} (${user.email})`;
}

常见类型

类型示例说明
string"你好"字符串
number42, 3.14数字
booleantrue, false布尔值
string[]["a", "b"]字符串数组
number[][1, 2, 3]数字数组
T | nullstring | null联合类型(或)
T | undefinednumber | undefined可能不存在
void函数无返回值
any任何值尽量避免使用

9. 为什么用 TypeScript?

提前发现错误

// JavaScript —— 运行时才知道错了
function greet(name) {
  return `你好,${name}`;
}
greet(42); // 不会报错,但结果不是你要的
 
// TypeScript —— 写代码时就告诉你错了
function greet(name: string): string {
  return `你好,${name}`;
}
greet(42); // ❌ 编辑器直接报红:number 不能赋值给 string

AI 写 TS 代码质量更高

场景JavaScriptTypeScript
AI 生成函数可能猜错参数类型类型明确,一次生成就能用
代码重构改一个漏一串类型检查帮你发现所有受影响处
代码提示(IntelliSense)不准确极其精准
协作开发靠注释沟通类型即文档

TIP

在 AI 编程时代,TypeScript 比 JavaScript 更有优势。 因为明确的类型约束让 AI 生成的代码更准确、更少出错。


10. 在 Next.js 中使用 TypeScript

Next.js 项目默认使用 TypeScript。您会看到三种文件后缀:

后缀含义
.tsTypeScript 纯逻辑文件
.tsxTypeScript + JSX(含 UI 组件)
.js / .jsx纯 JavaScript(旧项目)
// src/app/page.tsx —— Next.js 的首页
import { Metadata } from "next";
 
// 定义元数据类型
export const metadata: Metadata = {
  title: "我的应用",
  description: "这是我的 Next.js 应用"
};
 
// 定义组件属性
interface HomeProps {
  name?: string;
}
 
// 默认导出的组件
export default function Home({ name = "朋友" }: HomeProps) {
  return (
    <div>
      <h1>你好,{name}!</h1>
    </div>
  );
}
// src/app/api/hello/route.ts —— Next.js API 路由
import { NextRequest, NextResponse } from "next/server";
 
export async function GET(request: NextRequest) {
  return NextResponse.json({
    message: "Hello World"
  });
}

NOTE

不用记住所有语法。当你在 Cursor/TRAE 中写代码时,AI 会自动帮你写好类型注解。你只需要能看懂它们的含义


动手练习

练习任务

  1. 变量练习:在浏览器的开发者工具(F12 → Console)中,输入以下代码试试:

    const myName = "你的名字";
    console.log(`你好,${myName}!`);
  2. 函数练习:在 Console 中定义一个箭头函数,计算两数之和。

  3. 类型练习:在项目中打开任意 .ts.tsx 文件,找一找哪里用到了 interface 或类型注解。

  4. AI 辅助:在 Cursor/TRAE 中提问:

    “请帮我解释当前项目文件中所有的 TypeScript 类型定义,告诉我每个类型代表什么意思。“

函数练习参考答案
const add = (a: number, b: number): number => a + b;
// 或纯 JS 版
const add = (a, b) => a + b;
 
console.log(add(3, 5)); // 8

下一步

学完 JavaScript 和 TypeScript 基础后,接下来学习如何让页面变得更好看:

补充课06:Tailwind CSS →

或者复习核心课程:

第05课:前后端与Next.js →