JavaScript 语法完全指南:从入门到精通
本文是一篇面向初学者的 JavaScript 语法教程,从最基础的概念到高级特性,每个知识点都配有详细的示例代码和解释,让小白也能轻松掌握 JavaScript。
📚 目录
- [一、JavaScript 简介](#一、JavaScript 简介)
- 二、变量与数据类型
- 三、运算符
- 四、流程控制
- 五、函数
- 六、对象与数组
- 七、字符串操作
- [八、ES6+ 新特性](#八、ES6+ 新特性)
- 九、异步编程
- [十、DOM 操作](#十、DOM 操作)
- 十一、常见错误与调试
- 十二、最佳实践
一、JavaScript 简介
1.1 什么是 JavaScript?
JavaScript (简称 JS)是一种解释型的编程语言,主要用于:
- 网页交互:让网页"动起来"(点击按钮、表单验证等)
- 后端开发:Node.js 让 JavaScript 可以在服务器运行
- 移动开发:React Native、Ionic 等框架
- 桌面应用:Electron 框架
1.2 JavaScript 的特点
- ✅ 解释型语言:不需要编译,浏览器直接执行
- ✅ 弱类型语言:变量类型可以自动转换
- ✅ 动态语言:可以在运行时修改对象和函数
- ✅ 跨平台:可以在浏览器、服务器、移动设备运行
1.3 第一个 JavaScript 程序
javascript
// 在浏览器控制台(F12)中运行
console.log("Hello, World!");
// 输出:Hello, World!
说明:
console.log():在控制台输出内容//:单行注释/* */:多行注释
二、变量与数据类型
2.1 变量声明
var(旧方式,不推荐)
javascript
var name = "张三";
var age = 20;
var isStudent = true;
// 可以重复声明(不推荐)
var name = "李四"; // 不会报错,但会覆盖之前的值
let(推荐,块级作用域)
javascript
let name = "张三";
let age = 20;
// 不能重复声明
let name = "李四"; // ❌ 报错:Identifier 'name' has already been declared
// 可以重新赋值
name = "李四"; // ✅ 正确
const(常量,推荐)
javascript
const PI = 3.14159;
const MAX_SIZE = 100;
// 不能重新赋值
PI = 3.14; // ❌ 报错:Assignment to constant variable
// 必须初始化
const name; // ❌ 报错:Missing initializer in const declaration
选择建议:
- ✅ 优先使用
const:如果值不会改变 - ✅ 使用
let:如果值需要改变 - ❌ 避免使用
var:有作用域问题
2.2 数据类型
JavaScript 有 8 种数据类型:
1. 基本类型(Primitive Types)
Number(数字)
javascript
let age = 20; // 整数
let price = 99.99; // 小数
let temperature = -10; // 负数
let infinity = Infinity; // 无穷大
let notANumber = NaN; // 不是数字
// 科学计数法
let bigNumber = 1e6; // 1000000
let smallNumber = 1e-3; // 0.001
// 类型检查
console.log(typeof age); // "number"
String(字符串)
javascript
let name1 = "张三"; // 双引号
let name2 = '李四'; // 单引号
let name3 = `王五`; // 模板字符串(ES6)
// 字符串拼接
let fullName = name1 + " " + name2; // "张三 李四"
// 模板字符串(推荐)
let message = `你好,我是${name1}`; // "你好,我是张三"
// 字符串方法
let text = "Hello World";
console.log(text.length); // 11(长度)
console.log(text.toUpperCase()); // "HELLO WORLD"
console.log(text.toLowerCase()); // "hello world"
console.log(text.substring(0, 5)); // "Hello"
Boolean(布尔值)
javascript
let isStudent = true;
let isWorking = false;
// 布尔值转换
console.log(Boolean(1)); // true
console.log(Boolean(0)); // false
console.log(Boolean("")); // false(空字符串)
console.log(Boolean("hello")); // true(非空字符串)
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
Undefined(未定义)
javascript
let name;
console.log(name); // undefined
console.log(typeof name); // "undefined"
// 未赋值的变量默认是 undefined
Null(空值)
javascript
let user = null;
console.log(user); // null
console.log(typeof user); // "object"(这是 JavaScript 的 bug)
// null 表示"空值",undefined 表示"未定义"
Symbol(符号,ES6)
javascript
// 创建唯一的标识符
let id1 = Symbol("id");
let id2 = Symbol("id");
console.log(id1 === id2); // false(每个 Symbol 都是唯一的)
// 常用于对象属性名
let user = {
[id1]: "12345"
};
BigInt(大整数,ES2020)
javascript
// 处理超出 Number 范围的整数
let bigNumber = 9007199254740991n; // 注意末尾的 n
let anotherBig = BigInt("9007199254740991");
console.log(bigNumber + 1n); // 9007199254740992n
2. 引用类型(Reference Types)
Object(对象)
javascript
// 对象字面量
let user = {
name: "张三",
age: 20,
isStudent: true,
sayHello: function() {
console.log("你好!");
}
};
// 访问属性
console.log(user.name); // "张三"
console.log(user["age"]); // 20(方括号方式)
user.sayHello(); // "你好!"
// 添加属性
user.email = "zhangsan@example.com";
// 删除属性
delete user.isStudent;
Array(数组)
javascript
// 数组字面量
let fruits = ["苹果", "香蕉", "橙子"];
// 访问元素
console.log(fruits[0]); // "苹果"(索引从 0 开始)
console.log(fruits.length); // 3
// 添加元素
fruits.push("葡萄"); // 末尾添加
fruits.unshift("草莓"); // 开头添加
// 删除元素
fruits.pop(); // 删除最后一个
fruits.shift(); // 删除第一个
// 遍历数组
fruits.forEach(function(fruit) {
console.log(fruit);
});
2.3 类型转换
隐式转换(自动转换)
javascript
// 数字转字符串
let num = 10;
let str = num + ""; // "10"(加空字符串)
// 字符串转数字
let str2 = "20";
let num2 = +str2; // 20(一元加号)
let num3 = str2 * 1; // 20(乘法)
// 布尔值转换
let bool = !!str2; // true(双重取反)
显式转换(手动转换)
javascript
// 转字符串
String(123); // "123"
(123).toString(); // "123"
// 转数字
Number("123"); // 123
parseInt("123.45"); // 123(整数)
parseFloat("123.45"); // 123.45(小数)
// 转布尔值
Boolean(1); // true
Boolean(0); // false
2.4 类型检查
javascript
// typeof 运算符
typeof 123; // "number"
typeof "hello"; // "string"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof null; // "object"(bug)
typeof {}; // "object"
typeof []; // "object"(数组也是对象)
// instanceof 运算符(检查对象类型)
[] instanceof Array; // true
{} instanceof Object; // true
// Array.isArray()(检查是否为数组)
Array.isArray([]); // true
Array.isArray({}); // false
三、运算符
3.1 算术运算符
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(幂运算,ES2016)
// 自增自减
let x = 5;
x++; // x = 6(后置)
++x; // x = 7(前置)
x--; // x = 6(后置)
--x; // x = 5(前置)
// 前置和后置的区别
let y = 5;
let result1 = ++y; // y = 6, result1 = 6(先自增,再赋值)
let z = 5;
let result2 = z++; // z = 6, result2 = 5(先赋值,再自增)
3.2 赋值运算符
javascript
let x = 10;
x += 5; // x = x + 5 = 15
x -= 3; // x = x - 3 = 12
x *= 2; // x = x * 2 = 24
x /= 4; // x = x / 4 = 6
x %= 5; // x = x % 5 = 1
3.3 比较运算符
javascript
let a = 5;
let b = "5";
// 相等比较
console.log(a == b); // true(值相等,类型不同也会相等)
console.log(a === b); // false(严格相等,值和类型都要相等)
console.log(a != b); // false(值不相等)
console.log(a !== b); // true(严格不相等)
// 大小比较
console.log(5 > 3); // true
console.log(5 < 3); // false
console.log(5 >= 5); // true
console.log(5 <= 3); // false
// 推荐使用严格相等(===)和严格不相等(!==)
3.4 逻辑运算符
javascript
let x = 5;
let y = 10;
// 逻辑与(AND)
console.log(x > 0 && y > 0); // true(两个都为 true)
console.log(x > 0 && y < 0); // false(有一个为 false)
// 逻辑或(OR)
console.log(x > 0 || y < 0); // true(有一个为 true)
console.log(x < 0 || y < 0); // false(两个都为 false)
// 逻辑非(NOT)
console.log(!true); // false
console.log(!false); // true
// 短路求值
let result = x > 0 && y++; // y++ 会执行(因为 x > 0 为 true)
let result2 = x < 0 && y++; // y++ 不会执行(短路)
3.5 三元运算符(条件运算符)
javascript
let age = 20;
let status = age >= 18 ? "成年人" : "未成年人";
console.log(status); // "成年人"
// 等价于
let status2;
if (age >= 18) {
status2 = "成年人";
} else {
status2 = "未成年人";
}
// 嵌套三元运算符
let score = 85;
let grade = score >= 90 ? "优秀" :
score >= 80 ? "良好" :
score >= 60 ? "及格" : "不及格";
console.log(grade); // "良好"
3.6 其他运算符
javascript
// 空值合并运算符(??,ES2020)
let name = null;
let displayName = name ?? "匿名"; // "匿名"(如果 name 为 null 或 undefined)
// 可选链运算符(?.,ES2020)
let user = {
name: "张三",
address: {
city: "北京"
}
};
console.log(user.address?.city); // "北京"
console.log(user.address?.zipCode); // undefined(不会报错)
// 展开运算符(...,ES6)
let arr1 = [1, 2, 3];
let arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
let obj1 = { a: 1, b: 2 };
let obj2 = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }
四、流程控制
4.1 if 语句
javascript
let age = 20;
// 单分支
if (age >= 18) {
console.log("成年人");
}
// 双分支
if (age >= 18) {
console.log("成年人");
} else {
console.log("未成年人");
}
// 多分支
if (age < 13) {
console.log("儿童");
} else if (age < 18) {
console.log("青少年");
} else if (age < 60) {
console.log("成年人");
} else {
console.log("老年人");
}
4.2 switch 语句
javascript
let day = 3;
let dayName;
switch (day) {
case 1:
dayName = "星期一";
break;
case 2:
dayName = "星期二";
break;
case 3:
dayName = "星期三";
break;
case 4:
dayName = "星期四";
break;
case 5:
dayName = "星期五";
break;
case 6:
case 7:
dayName = "周末";
break;
default:
dayName = "未知";
}
console.log(dayName); // "星期三"
// ⚠️ 注意:必须使用 break,否则会"穿透"到下一个 case
4.3 for 循环
javascript
// 传统 for 循环
for (let i = 0; i < 5; i++) {
console.log(i); // 0, 1, 2, 3, 4
}
// for...in 循环(遍历对象属性)
let person = { name: "张三", age: 20, city: "北京" };
for (let key in person) {
console.log(key + ": " + person[key]);
}
// 输出:
// name: 张三
// age: 20
// city: 北京
// for...of 循环(遍历数组元素,ES6)
let fruits = ["苹果", "香蕉", "橙子"];
for (let fruit of fruits) {
console.log(fruit);
}
// 输出:
// 苹果
// 香蕉
// 橙子
4.4 while 循环
javascript
// while 循环
let i = 0;
while (i < 5) {
console.log(i); // 0, 1, 2, 3, 4
i++;
}
// do...while 循环(至少执行一次)
let j = 0;
do {
console.log(j); // 0, 1, 2, 3, 4
j++;
} while (j < 5);
4.5 循环控制
javascript
// break:跳出循环
for (let i = 0; i < 10; i++) {
if (i === 5) {
break; // 当 i = 5 时跳出循环
}
console.log(i); // 0, 1, 2, 3, 4
}
// continue:跳过本次循环
for (let i = 0; i < 10; i++) {
if (i === 5) {
continue; // 跳过 i = 5 这次循环
}
console.log(i); // 0, 1, 2, 3, 4, 6, 7, 8, 9
}
// 标签(label):跳出多层循环
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) {
break outer; // 跳出外层循环
}
console.log(i, j);
}
}
五、函数
5.1 函数声明
javascript
// 函数声明
function greet(name) {
return "你好," + name + "!";
}
console.log(greet("张三")); // "你好,张三!"
// 函数表达式
const greet2 = function(name) {
return "你好," + name + "!";
};
// 箭头函数(ES6,推荐)
const greet3 = (name) => {
return "你好," + name + "!";
};
// 箭头函数简化(单行)
const greet4 = (name) => "你好," + name + "!";
// 箭头函数简化(单个参数)
const greet5 = name => "你好," + name + "!";
5.2 函数参数
javascript
// 默认参数(ES6)
function greet(name = "匿名") {
return "你好," + name + "!";
}
console.log(greet()); // "你好,匿名!"
console.log(greet("张三")); // "你好,张三!"
// 剩余参数(ES6)
function sum(...numbers) {
let total = 0;
for (let num of numbers) {
total += num;
}
return total;
}
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4, 5)); // 15
// 参数解构(ES6)
function greetUser({ name, age }) {
return `你好,${name},你今年${age}岁!`;
}
console.log(greetUser({ name: "张三", age: 20 })); // "你好,张三,你今年20岁!"
5.3 返回值
javascript
// 有返回值
function add(a, b) {
return a + b;
}
let result = add(3, 5); // 8
// 无返回值(返回 undefined)
function sayHello(name) {
console.log("你好," + name);
// 没有 return,默认返回 undefined
}
let result2 = sayHello("张三"); // undefined
// 提前返回
function checkAge(age) {
if (age < 0) {
return "年龄不能为负数";
}
if (age < 18) {
return "未成年人";
}
return "成年人";
}
5.4 作用域
javascript
// 全局作用域
let globalVar = "全局变量";
function test() {
// 函数作用域
let localVar = "局部变量";
console.log(globalVar); // "全局变量"(可以访问全局变量)
console.log(localVar); // "局部变量"
}
test();
console.log(globalVar); // "全局变量"
console.log(localVar); // ❌ 报错:localVar is not defined
// 块级作用域(let、const)
if (true) {
let blockVar = "块级变量";
console.log(blockVar); // "块级变量"
}
console.log(blockVar); // ❌ 报错:blockVar is not defined
// var 没有块级作用域(不推荐)
if (true) {
var oldVar = "旧变量";
}
console.log(oldVar); // "旧变量"(可以访问)
5.5 闭包
javascript
// 闭包:函数可以访问外部作用域的变量
function outer() {
let count = 0;
function inner() {
count++;
return count;
}
return inner;
}
const counter = outer();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
// 闭包的应用:私有变量
function createCounter() {
let count = 0;
return {
increment: () => ++count,
decrement: () => --count,
getCount: () => count
};
}
const myCounter = createCounter();
console.log(myCounter.increment()); // 1
console.log(myCounter.increment()); // 2
console.log(myCounter.getCount()); // 2
5.6 高阶函数
javascript
// 函数作为参数
function processArray(arr, callback) {
let result = [];
for (let item of arr) {
result.push(callback(item));
}
return result;
}
let numbers = [1, 2, 3, 4, 5];
let doubled = processArray(numbers, x => x * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// 函数作为返回值
function multiplyBy(factor) {
return function(number) {
return number * factor;
};
}
const double = multiplyBy(2);
const triple = multiplyBy(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
5.7 数组方法(函数式编程)
javascript
let numbers = [1, 2, 3, 4, 5];
// map:映射(转换每个元素)
let doubled = numbers.map(x => x * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// filter:过滤(筛选元素)
let evens = numbers.filter(x => x % 2 === 0);
console.log(evens); // [2, 4]
// reduce:归约(累积计算)
let sum = numbers.reduce((acc, x) => acc + x, 0);
console.log(sum); // 15
// forEach:遍历(执行操作)
numbers.forEach(x => console.log(x)); // 1, 2, 3, 4, 5
// find:查找(返回第一个匹配的元素)
let found = numbers.find(x => x > 3);
console.log(found); // 4
// some:检查(是否有元素满足条件)
let hasEven = numbers.some(x => x % 2 === 0);
console.log(hasEven); // true
// every:检查(是否所有元素都满足条件)
let allPositive = numbers.every(x => x > 0);
console.log(allPositive); // true
六、对象与数组
6.1 对象(Object)
javascript
// 创建对象
let user = {
name: "张三",
age: 20,
email: "zhangsan@example.com",
sayHello: function() {
return "你好,我是" + this.name;
}
};
// 访问属性
console.log(user.name); // "张三"
console.log(user["age"]); // 20
console.log(user.sayHello()); // "你好,我是张三"
// 添加属性
user.city = "北京";
user["country"] = "中国";
// 修改属性
user.age = 21;
// 删除属性
delete user.email;
// 检查属性是否存在
console.log("name" in user); // true
console.log(user.hasOwnProperty("name")); // true
// 遍历对象
for (let key in user) {
console.log(key + ": " + user[key]);
}
// Object.keys()、Object.values()、Object.entries()
console.log(Object.keys(user)); // ["name", "age", "city", "country", "sayHello"]
console.log(Object.values(user)); // ["张三", 21, "北京", "中国", function...]
console.log(Object.entries(user)); // [["name", "张三"], ["age", 21], ...]
6.2 数组(Array)
javascript
// 创建数组
let fruits = ["苹果", "香蕉", "橙子"];
let numbers = new Array(1, 2, 3);
// 访问元素
console.log(fruits[0]); // "苹果"
console.log(fruits.length); // 3
// 添加元素
fruits.push("葡萄"); // 末尾添加
fruits.unshift("草莓"); // 开头添加
fruits.splice(2, 0, "芒果"); // 索引 2 处插入
// 删除元素
fruits.pop(); // 删除最后一个
fruits.shift(); // 删除第一个
fruits.splice(1, 1); // 删除索引 1 的元素
// 查找元素
console.log(fruits.indexOf("香蕉")); // 1(索引)
console.log(fruits.includes("苹果")); // true(是否存在)
// 数组方法
let numbers = [1, 2, 3, 4, 5];
// 切片(不改变原数组)
let slice = numbers.slice(1, 3); // [2, 3]
// 连接(不改变原数组)
let combined = numbers.concat([6, 7]); // [1, 2, 3, 4, 5, 6, 7]
// 反转(改变原数组)
numbers.reverse(); // [5, 4, 3, 2, 1]
// 排序(改变原数组)
let unsorted = [3, 1, 4, 1, 5];
unsorted.sort(); // [1, 1, 3, 4, 5]
unsorted.sort((a, b) => b - a); // [5, 4, 3, 1, 1](降序)
6.3 解构赋值(ES6)
javascript
// 数组解构
let [a, b, c] = [1, 2, 3];
console.log(a, b, c); // 1, 2, 3
let [x, , z] = [1, 2, 3]; // 跳过中间的元素
console.log(x, z); // 1, 3
let [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest); // [2, 3, 4, 5]
// 对象解构
let { name, age } = { name: "张三", age: 20, city: "北京" };
console.log(name, age); // "张三", 20
let { name: userName, age: userAge } = { name: "张三", age: 20 };
console.log(userName, userAge); // "张三", 20(重命名)
// 默认值
let { name = "匿名", age = 0 } = { name: "张三" };
console.log(name, age); // "张三", 0
// 嵌套解构
let user = {
name: "张三",
address: {
city: "北京",
zipCode: "100000"
}
};
let { address: { city } } = user;
console.log(city); // "北京"
七、字符串操作
7.1 字符串方法
javascript
let text = "Hello World";
// 长度
console.log(text.length); // 11
// 大小写转换
console.log(text.toUpperCase()); // "HELLO WORLD"
console.log(text.toLowerCase()); // "hello world"
// 查找
console.log(text.indexOf("World")); // 6(首次出现的位置)
console.log(text.lastIndexOf("o")); // 7(最后出现的位置)
console.log(text.includes("World")); // true(是否包含)
console.log(text.startsWith("Hello")); // true(是否以...开头)
console.log(text.endsWith("World")); // true(是否以...结尾)
// 截取
console.log(text.substring(0, 5)); // "Hello"(开始索引,结束索引)
console.log(text.slice(0, 5)); // "Hello"(开始索引,结束索引)
console.log(text.slice(-5)); // "World"(负数表示从末尾开始)
// 替换
console.log(text.replace("World", "JavaScript")); // "Hello JavaScript"
console.log(text.replaceAll("l", "L")); // "HeLLo WorLd"(ES2021)
// 分割
let words = text.split(" "); // ["Hello", "World"]
let chars = text.split(""); // ["H", "e", "l", "l", "o", " ", "W", "o", "r", "l", "d"]
// 去除空白
let spaced = " Hello World ";
console.log(spaced.trim()); // "Hello World"(去除首尾空白)
console.log(spaced.trimStart()); // "Hello World "(去除开头空白)
console.log(spaced.trimEnd()); // " Hello World"(去除结尾空白)
// 重复
console.log("Hello".repeat(3)); // "HelloHelloHello"
7.2 模板字符串(ES6)
javascript
let name = "张三";
let age = 20;
// 传统方式
let message1 = "你好,我是" + name + ",今年" + age + "岁";
// 模板字符串(推荐)
let message2 = `你好,我是${name},今年${age}岁`;
// 多行字符串
let multiLine = `
第一行
第二行
第三行
`;
// 表达式
let a = 5;
let b = 10;
let result = `${a} + ${b} = ${a + b}`; // "5 + 10 = 15"
// 函数调用
function greet(name) {
return `你好,${name}!`;
}
let greeting = `${greet("张三")}`; // "你好,张三!"
八、ES6+ 新特性
8.1 let 和 const
javascript
// let:块级作用域变量
if (true) {
let x = 10;
}
console.log(x); // ❌ 报错:x is not defined
// const:常量
const PI = 3.14159;
PI = 3.14; // ❌ 报错:Assignment to constant variable
// const 对象可以修改属性
const user = { name: "张三" };
user.name = "李四"; // ✅ 可以
user = {}; // ❌ 不可以(不能重新赋值)
8.2 箭头函数
javascript
// 传统函数
function add(a, b) {
return a + b;
}
// 箭头函数
const add2 = (a, b) => a + b;
// 箭头函数的特点
let obj = {
name: "张三",
// 传统函数:this 指向 obj
sayHello1: function() {
console.log("你好," + this.name);
},
// 箭头函数:this 指向外层作用域(window)
sayHello2: () => {
console.log("你好," + this.name); // undefined
}
};
obj.sayHello1(); // "你好,张三"
obj.sayHello2(); // "你好,undefined"
8.3 解构赋值
javascript
// 数组解构
let [a, b] = [1, 2];
// 对象解构
let { name, age } = { name: "张三", age: 20 };
// 函数参数解构
function greet({ name, age }) {
return `你好,${name},${age}岁`;
}
8.4 展开运算符
javascript
// 数组展开
let arr1 = [1, 2, 3];
let arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
// 对象展开
let obj1 = { a: 1, b: 2 };
let obj2 = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }
// 函数参数展开
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3); // 6
8.5 Promise 和 async/await
javascript
// Promise
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("数据获取成功");
}, 1000);
});
}
fetchData()
.then(data => console.log(data))
.catch(error => console.error(error));
// async/await(ES2017)
async function getData() {
try {
let data = await fetchData();
console.log(data);
} catch (error) {
console.error(error);
}
}
8.6 类(Class,ES6)
javascript
// 类定义
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
return `你好,我是${this.name},${this.age}岁`;
}
}
// 创建实例
let person = new Person("张三", 20);
console.log(person.sayHello()); // "你好,我是张三,20岁"
// 继承
class Student extends Person {
constructor(name, age, school) {
super(name, age);
this.school = school;
}
study() {
return `${this.name}在${this.school}学习`;
}
}
let student = new Student("李四", 18, "北京大学");
console.log(student.sayHello()); // "你好,我是李四,18岁"
console.log(student.study()); // "李四在北京大学学习"
九、异步编程
9.1 回调函数
javascript
// 回调函数(Callback)
function fetchData(callback) {
setTimeout(() => {
callback("数据获取成功");
}, 1000);
}
fetchData(function(data) {
console.log(data);
});
// 回调地狱(不推荐)
fetchData(function(data1) {
fetchData(function(data2) {
fetchData(function(data3) {
console.log(data1, data2, data3);
});
});
});
9.2 Promise
javascript
// Promise 创建
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
let success = true;
if (success) {
resolve("操作成功");
} else {
reject("操作失败");
}
}, 1000);
});
// Promise 使用
promise
.then(result => {
console.log(result); // "操作成功"
return "下一步";
})
.then(result => {
console.log(result); // "下一步"
})
.catch(error => {
console.error(error); // "操作失败"
})
.finally(() => {
console.log("完成"); // 无论成功失败都会执行
});
// Promise.all:等待所有 Promise 完成
Promise.all([
fetchData1(),
fetchData2(),
fetchData3()
])
.then(results => {
console.log(results); // [结果1, 结果2, 结果3]
});
// Promise.race:第一个完成的 Promise
Promise.race([
fetchData1(),
fetchData2()
])
.then(result => {
console.log(result); // 第一个完成的结果
});
9.3 async/await
javascript
// async/await(推荐)
async function fetchUserData() {
try {
let user = await fetchUser();
let posts = await fetchPosts(user.id);
let comments = await fetchComments(posts[0].id);
return { user, posts, comments };
} catch (error) {
console.error("错误:", error);
throw error;
}
}
fetchUserData()
.then(data => console.log(data))
.catch(error => console.error(error));
// 并行执行(使用 Promise.all)
async function fetchAllData() {
let [user, posts, comments] = await Promise.all([
fetchUser(),
fetchPosts(),
fetchComments()
]);
return { user, posts, comments };
}
9.4 Fetch API
javascript
// Fetch API(现代浏览器)
fetch("https://api.example.com/data")
.then(response => {
if (!response.ok) {
throw new Error("网络错误");
}
return response.json();
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error("错误:", error);
});
// 使用 async/await
async function fetchData() {
try {
let response = await fetch("https://api.example.com/data");
if (!response.ok) {
throw new Error("网络错误");
}
let data = await response.json();
console.log(data);
} catch (error) {
console.error("错误:", error);
}
}
// POST 请求
async function postData(url, data) {
let response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
return response.json();
}
十、DOM 操作
10.1 选择元素
javascript
// 选择单个元素
let element = document.getElementById("myId");
let element2 = document.querySelector(".myClass");
let element3 = document.querySelector("#myId");
// 选择多个元素
let elements = document.getElementsByClassName("myClass");
let elements2 = document.getElementsByTagName("div");
let elements3 = document.querySelectorAll(".myClass");
// 遍历元素
elements3.forEach(element => {
console.log(element);
});
10.2 修改内容
javascript
// 修改文本内容
let element = document.getElementById("myId");
element.textContent = "新文本";
element.innerText = "新文本";
element.innerHTML = "<strong>新文本</strong>";
// 修改属性
element.setAttribute("class", "newClass");
element.className = "newClass";
element.id = "newId";
// 修改样式
element.style.color = "red";
element.style.fontSize = "20px";
element.style.backgroundColor = "yellow";
10.3 创建和删除元素
javascript
// 创建元素
let newDiv = document.createElement("div");
newDiv.textContent = "新元素";
newDiv.className = "myClass";
// 添加到页面
let parent = document.getElementById("parent");
parent.appendChild(newDiv);
// 插入元素
let beforeElement = document.getElementById("before");
parent.insertBefore(newDiv, beforeElement);
// 删除元素
parent.removeChild(newDiv);
newDiv.remove(); // 现代方式
10.4 事件处理
javascript
// 添加事件监听器
let button = document.getElementById("myButton");
// 方式一:addEventListener(推荐)
button.addEventListener("click", function() {
console.log("按钮被点击了");
});
// 方式二:onclick(不推荐)
button.onclick = function() {
console.log("按钮被点击了");
};
// 事件对象
button.addEventListener("click", function(event) {
console.log(event.target); // 触发事件的元素
console.log(event.type); // 事件类型("click")
event.preventDefault(); // 阻止默认行为
event.stopPropagation(); // 阻止事件冒泡
});
// 常见事件
element.addEventListener("click", handler); // 点击
element.addEventListener("mouseenter", handler); // 鼠标进入
element.addEventListener("mouseleave", handler); // 鼠标离开
element.addEventListener("input", handler); // 输入
element.addEventListener("submit", handler); // 提交表单
element.addEventListener("load", handler); // 加载完成
十一、常见错误与调试
11.1 常见错误
javascript
// 1. 未定义变量
console.log(undefinedVar); // ❌ ReferenceError: undefinedVar is not defined
// 2. 类型错误
let num = 10;
num.toUpperCase(); // ❌ TypeError: num.toUpperCase is not a function
// 3. 语法错误
let x = 10; // ❌ SyntaxError: Unexpected token
// 4. 空值错误
let user = null;
console.log(user.name); // ❌ TypeError: Cannot read property 'name' of null
// 5. 作用域错误
function test() {
if (true) {
var x = 10;
}
console.log(x); // 10(var 没有块级作用域)
}
11.2 调试技巧
javascript
// console.log:输出信息
console.log("变量值:", variable);
// console.error:输出错误
console.error("错误信息:", error);
// console.warn:输出警告
console.warn("警告信息:", warning);
// console.table:表格形式输出
let users = [
{ name: "张三", age: 20 },
{ name: "李四", age: 25 }
];
console.table(users);
// debugger:断点调试
function complexFunction() {
debugger; // 浏览器会在这里暂停
// 代码...
}
// try...catch:错误处理
try {
// 可能出错的代码
let result = riskyOperation();
} catch (error) {
// 错误处理
console.error("错误:", error.message);
} finally {
// 无论是否出错都会执行
console.log("完成");
}
十二、最佳实践
12.1 代码风格
javascript
// ✅ 使用 const 和 let,避免 var
const PI = 3.14159;
let count = 0;
// ✅ 使用箭头函数
const add = (a, b) => a + b;
// ✅ 使用模板字符串
const message = `你好,${name}!`;
// ✅ 使用解构赋值
const { name, age } = user;
// ✅ 使用严格相等
if (x === y) { // 而不是 x == y
// ...
}
// ✅ 使用有意义的变量名
const userName = "张三"; // 而不是 u 或 n
12.2 性能优化
javascript
// ✅ 缓存 DOM 查询
const element = document.getElementById("myId");
// 多次使用 element,而不是重复查询
// ✅ 使用事件委托
document.addEventListener("click", function(event) {
if (event.target.classList.contains("button")) {
// 处理点击
}
});
// ✅ 避免全局变量
(function() {
// 局部作用域
let localVar = "局部变量";
})();
// ✅ 使用数组方法而不是循环
let doubled = numbers.map(x => x * 2); // 而不是 for 循环
12.3 代码组织
javascript
// ✅ 模块化(ES6 Modules)
// math.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
// main.js
import { add, subtract } from './math.js';
console.log(add(1, 2)); // 3
// ✅ 使用对象组织代码
const Calculator = {
add: (a, b) => a + b,
subtract: (a, b) => a - b,
multiply: (a, b) => a * b
};
// ✅ 使用类组织代码
class Calculator {
add(a, b) {
return a + b;
}
subtract(a, b) {
return a - b;
}
}
十三、总结
13.1 核心概念
- 变量 :使用
let和const,避免var - 数据类型:8 种类型(Number、String、Boolean、Undefined、Null、Symbol、BigInt、Object)
- 函数:函数声明、函数表达式、箭头函数
- 对象和数组:解构赋值、展开运算符
- 异步编程:Promise、async/await
13.2 学习路径
- 基础语法:变量、数据类型、运算符、流程控制
- 函数:函数定义、参数、返回值、作用域
- 对象和数组:创建、访问、修改、遍历
- ES6+ 特性:let/const、箭头函数、解构、模板字符串
- 异步编程:Promise、async/await
- DOM 操作:选择元素、修改内容、事件处理
13.3 推荐资源
- MDN Web Docs:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
- JavaScript.info:https://zh.javascript.info/
- ES6 入门教程:https://es6.ruanyifeng.com/
希望这篇教程能帮助你掌握 JavaScript!多写代码,多实践,才能熟练掌握。