一、变量与作用域
1. 变量声明详解
// let 和 const(块级作用域)
{
let a = 10;
const b = 20;
// a 可修改,b 不可修改
a = 30; // ✅
// b = 40; ❌ 报错
}
// console.log(a); ❌ 超出作用域
// var(函数作用域,存在变量提升)
function testVar() {
console.log(x); // undefined(变量提升)
var x = 5;
}
testVar();
// 变量提升示例
console.log(y); // ❌ 报错(let/const 不会提升)
let y = 10;
2. 数据类型深入
// 类型检测
console.log(typeof "Hello"); // "string"
console.log(typeof null); // "object"(历史遗留问题)
console.log(Array.isArray([]));// true
// 类型转换
let numStr = "123";
console.log(Number(numStr)); // 123(显式转换)
console.log(+"456"); // 456(隐式转换)
// 引用类型陷阱
let arr1 = [1, 2];
let arr2 = arr1;
arr2.push(3);
console.log(arr1); // [1, 2, 3](共享内存地址)
二、运算符与表达式
1. 特殊运算符
// 三元运算符
let price = 100;
let discount = price > 80 ? 0.9 : 1;
console.log(discount); // 0.9
// 空值合并运算符(??)
let input = null;
let value = input ?? "default"; // "default"
// 可选链(?.)
const user = { address: { city: "Beijing" } };
console.log(user?.address?.city); // "Beijing"
console.log(user?.phone?.number); // undefined(不报错)
2. 逻辑运算的短路特性
// && 短路:左侧为假时直接返回左侧
console.log(0 && "Hello"); // 0
// || 短路:左侧为真时直接返回左侧
console.log("Hi" || "Fallback"); // "Hi"
三、流程控制进阶
1. 循环的更多用法
// for...of 遍历数组
const fruits = ["apple", "banana"];
for (const fruit of fruits) {
console.log(fruit); // apple, banana
}
// for...in 遍历对象属性
const obj = { a: 1, b: 2 };
for (const key in obj) {
console.log(key, obj[key]); // a 1, b 2
}
// break 和 continue
for (let i = 0; i < 10; i++) {
if (i === 5) break; // 退出循环
if (i % 2 === 0) continue; // 跳过本次循环
console.log(i); // 输出 1, 3
}
2. 错误处理(try...catch)
try {
let result = x / 0; // 假设 x 未定义
} catch (error) {
console.log("错误信息:", error.message); // x is not defined
} finally {
console.log("无论如何都会执行");
}
四、函数深入
1. 函数作用域与闭包
function outer() {
let count = 0;
return function inner() {
count++;
console.log(count);
};
}
const counter = outer();
counter(); // 1
counter(); // 2(闭包保留 count 的状态)
2. 参数传递机制
// 基本类型按值传递
let num = 10;
function changeNum(n) { n = 20; }
changeNum(num);
console.log(num); // 10(未改变)
// 引用类型按引用传递
let arr = [1, 2];
function changeArr(a) { a.push(3); }
changeArr(arr);
console.log(arr); // [1, 2, 3]
五、对象与数组高级操作
1. 对象方法
const person = {
name: "Alice",
greet: function() { console.log(`Hello, ${this.name}`); }
};
// 简写方法
const calculator = {
add(a, b) { return a + b; } // ES6 语法
};
2. 数组高阶函数
const numbers = [1, 2, 3, 4];
// filter
const even = numbers.filter(n => n % 2 === 0); // [2, 4]
// reduce
const sum = numbers.reduce((acc, curr) => acc + curr, 0); // 10
// 解构赋值
const [first, second] = numbers;
console.log(first); // 1
六、DOM 操作实战
1. 动态操作元素
<ul id="list"></ul>
const list = document.getElementById("list");
// 创建并添加元素
const li = document.createElement("li");
li.textContent = "新项目";
li.className = "item";
list.appendChild(li);
// 事件委托(动态元素监听)
list.addEventListener("click", (e) => {
if (e.target.tagName === "LI") {
e.target.style.textDecoration = "line-through";
}
});
2. 表单处理
<input type="text" id="username">
<button id="submitBtn">提交</button>
document.getElementById("submitBtn").addEventListener("click", () => {
const input = document.getElementById("username");
console.log("输入的值:", input.value); // 获取输入内容
input.value = ""; // 清空输入框
});
七、异步编程核心
1. Promise 链式调用
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("数据加载成功"), 1000);
});
}
fetchData()
.then(data => {
console.log(data); // "数据加载成功"
return "下一步处理";
})
.then(result => console.log(result))
.catch(error => console.error(error));
2. async/await
async function getUser() {
try {
const response = await fetch('https://api.example.com/user');
const data = await response.json();
console.log(data);
} catch (error) {
console.log("请求失败:", error);
}
}
getUser();
八、常见陷阱与最佳实践
1. 避免的常见错误
// 循环中的 var 陷阱
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 输出 3, 3, 3(改用 let 解决)
}
// 比较 NaN
console.log(NaN === NaN); // false(正确方法:Number.isNaN(NaN))
2. 代码规范建议
- 使用
===
替代 ==
- 优先使用
const
,其次 let
,避免 var
- 使用模板字符串(
)
- 启用严格模式:在文件顶部添加
'use strict';