🎯 课程目标
完成本课程后,你将能够:
- 理解JavaScript的基本语法和数据类型
- 掌握变量声明、运算符和表达式的使用
- 理解条件语句和循环结构的用法
- 能够编写简单的JavaScript函数
- 理解数组和对象的创建和操作方法
📖 JavaScript概述
JavaScript是Web开发的核心编程语言,它让网页变得交互和动态。JavaScript可以运行在浏览器中,也可以用于服务器端开发(Node.js)。
✨ JavaScript的特点
- 解释型语言:无需编译,直接由浏览器执行
- 动态类型:变量类型在运行时确定
- 事件驱动:通过响应用户事件实现交互
- 跨平台:几乎所有浏览器都支持
- 面向对象:支持面向对象编程范式
💻 变量与数据类型
JavaScript有三种声明变量的方式:var、let和const。现代开发推荐使用let和const。
步骤 1:变量声明
// 使用let声明变量(可以重新赋值)
let age = 25;
let name = "张三";
age = 26; // 允许修改
// 使用const声明常量(不能重新赋值)
const PI = 3.14159;
const greeting = "你好";
// 使用var声明(不推荐,作用域问题)
var oldStyle = "legacy";
// 变量命名规则
let myVariable = "有效"; // 字母、下划线、美元符号开头
let $element = "jQuery风格";
let _private = "私有变量";
let camelCase = "驼峰命名";
// let 123abc = "错误"; // 不能以数字开头
步骤 2:数据类型
// 基本类型
let str = "Hello"; // 字符串 String
let num = 42; // 数字 Number
let bigInt = 9007199254740991n; // 大整数 BigInt
let bool = true; // 布尔值 Boolean
let empty = null; // 空值
let notDefined; // 未定义 undefined
let sym = Symbol("唯一值"); // 符号 Symbol
// 引用类型
let arr = [1, 2, 3]; // 数组 Array
let obj = { name: "张三" }; // 对象 Object
let func = function() {}; // 函数 Function
// typeof操作符检查类型
console.log(typeof "Hello"); // "string"
console.log(typeof 42); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (历史原因)
console.log(typeof {}); // "object"
步骤 3:类型转换
// 字符串转数字
let strNum = "123";
let num1 = Number(strNum); // 123
let num2 = parseInt("123px"); // 123
let num3 = parseFloat("3.14"); // 3.14
let num4 = +"42"; // 42 (一元加号)
// 数字转字符串
let n = 42;
let s1 = String(n); // "42"
let s2 = n.toString(); // "42"
let s3 = n + ""; // "42"
// 转换为布尔值
let b1 = Boolean(1); // true
let b2 = Boolean(0); // false
let b3 = Boolean(""); // false
let b4 = Boolean("hello"); // true
let b5 = Boolean(null); // false
🔢 运算符
JavaScript提供多种运算符来处理数据。
算术运算符
let a = 10, 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
// 一元运算符
let x = 5;
console.log(++x); // 前置递增: 6
console.log(x++); // 后置递增: 6 (下一次使用时为7)
console.log(--x); // 前置递减
console.log(x--); // 后置递减
// 赋值运算符
let y = 10;
y += 5; // y = y + 5 = 15
y -= 3; // y = y - 3 = 12
y *= 2; // y = y * 2 = 24
y /= 4; // y = y / 4 = 6
y %= 4; // y = y % 4 = 2
比较运算符
let m = 5, n = "5";
// 相等性比较
console.log(m == n); // true (值相等,类型转换)
console.log(m === n); // false (严格相等,值和类型都要相同)
console.log(m != n); // false
console.log(m !== n); // true (严格不等)
console.log(m > n); // 大于: false
console.log(m < n); // 小于: false
console.log(m >= n); // 大于等于: true
console.log(m <= n); // 小于等于: true
// 特殊比较
console.log(0 == false); // true
console.log(0 === false); // false
console.log(null == undefined); // true
console.log(null === undefined); // false
console.log(NaN == NaN); // false (NaN不等于任何值,包括自己)
逻辑运算符
let p = true, q = false;
// 逻辑与 (AND)
console.log(p && q); // false
console.log(p && true); // true
// 逻辑或 (OR)
console.log(p || q); // true
console.log(q || q); // false
// 逻辑非 (NOT)
console.log(!p); // false
console.log(!q); // true
// 短路求值
console.log(true || "hello"); // true (短路)
console.log(false || "world"); // "world" (继续求值)
console.log(p && "结果"); // "结果"
console.log(q && "结果"); // false
// 三元运算符
let age = 18;
let status = age >= 18 ? "成年人" : "未成年人";
console.log(status); // "成年人"
🔄 流程控制
使用条件语句和循环来控制程序的执行流程。
条件语句
// if语句
let score = 85;
if (score >= 90) {
console.log("优秀");
} else if (score >= 70) {
console.log("良好");
} else if (score >= 60) {
console.log("及格");
} else {
console.log("不及格");
}
// switch语句
let day = new Date().getDay();
let dayName;
switch (day) {
case 0:
dayName = "星期日";
break;
case 1:
dayName = "星期一";
break;
case 2:
dayName = "星期二";
break;
default:
dayName = "未知";
}
// 简化的switch写法(箭头函数风格)
const actions = {
'add': () => '添加',
'update': () => '更新',
'delete': () => '删除'
};
console.log(actions['add']?.() || '未知操作');
循环语句
// for循环
for (let i = 0; i < 5; i++) {
console.log("第" + i + "次");
}
// while循环
let count = 0;
while (count < 3) {
console.log("计数: " + count);
count++;
}
// do...while循环(至少执行一次)
let num = 0;
do {
console.log("数字: " + num);
num++;
} while (num < 3);
// for...in循环(遍历对象属性)
let person = { name: "张三", age: 25, city: "北京" };
for (let key in person) {
console.log(key + ": " + person[key]);
}
// for...of循环(遍历可迭代对象)
let colors = ["红", "绿", "蓝"];
for (let color of colors) {
console.log(color);
}
// 跳出循环
for (let i = 0; i < 10; i++) {
if (i === 5) break; // 完全跳出循环
if (i === 3) continue; // 跳过本次,继续下一次
console.log(i);
}
📦 函数
函数是组织代码的基本单元,可以重复使用。
函数定义与调用
// 函数声明
function greet(name) {
return "你好, " + name + "!";
}
// 函数表达式
const multiply = function(a, b) {
return a * b;
};
// 箭头函数(ES6+)
const add = (a, b) => a + b;
// 默认参数
function createUser(name, role = "用户", age = 18) {
return { name, role, age };
}
// 调用函数
console.log(greet("张三")); // "你好, 张三!"
console.log(multiply(3, 4)); // 12
console.log(add(5, 7)); // 12
console.log(createUser("李四")); // { name: "李四", role: "用户", age: 18 }
剩余参数与展开运算符
// 剩余参数
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
// 展开运算符
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }
// 函数组合
function compose(...fns) {
return (x) => fns.reduceRight((acc, fn) => fn(acc), x);
}
📋 数组与对象
数组操作
// 数组创建
let fruits = ["苹果", "香蕉", "橙子"];
let numbers = new Array(1, 2, 3);
// 常用数组方法
fruits.push("葡萄"); // 添加到末尾: ["苹果", "香蕉", "橙子", "葡萄"]
fruits.pop(); // 移除末尾: ["苹果", "香蕉", "橙子"]
fruits.unshift("草莓"); // 添加到开头: ["草莓", "苹果", "香蕉", "橙子"]
fruits.shift(); // 移除开头: ["苹果", "香蕉", "橙子"]
// 遍历数组
fruits.forEach((fruit, index) => {
console.log(index + ": " + fruit);
});
// 数组转换
let upperFruits = fruits.map(f => f.toUpperCase());
let longFruits = fruits.filter(f => f.length > 2);
let total = [1, 2, 3, 4].reduce((sum, n) => sum + n, 0);
// 查找元素
let found = fruits.find(f => f === "香蕉");
let index = fruits.indexOf("橙子");
对象操作
// 对象创建
let person = {
name: "张三",
age: 25,
city: "北京",
sayHello() {
return "我是" + this.name;
}
};
// 访问属性
console.log(person.name); // "张三"
console.log(person["age"]); // 25
// 修改属性
person.age = 26;
person.job = "工程师"; // 添加新属性
// 删除属性
delete person.city;
// 对象展开
let user = { name: "李四", ...person, country: "中国" };
// 解构赋值
const { name, age } = person;
const { name: userName } = person; // 重命名
// 对象方法
Object.keys(person); // ["name", "age", "city", "sayHello"]
Object.values(person); // ["张三", 25, "北京", f]
Object.entries(person); // [["name", "张三"], ...]
⚠️ 常见问题
| 问题 | 原因分析 | 解决方案 |
|---|---|---|
| == 和 === 混淆 | ==会进行类型转换 | 尽量使用===严格相等 |
| var的作用域问题 | var没有块级作用域 | 使用let或const替代var |
| this指向错误 | 函数调用方式影响this | 使用箭头函数或bind固定this |
| 数组修改原数组 | push/pop等方法会修改原数组 | 使用map/filter返回新数组 |
| NaN比较问题 | NaN不等于任何值 | 使用isNaN()或Number.isNaN() |
✅ 课后练习
练习要求:请独立完成以下练习任务:
- 练习 1:编写函数计算数组中所有偶数的和
- 练习 2:创建一个学生对象数组,按年龄排序并输出
- 选做练习:实现一个简单的计算器,包含加减乘除功能