尚硅谷JavaScript(基础+高级)实战笔记全解析【从入门到精通】
1. JavaScript入门:从零开始搭建编程思维
第一次接触JavaScript时,我和大多数新手一样被各种术语绕得头晕。直到跟着尚硅谷的教程把代码敲进浏览器控制台,看到第一个"Hello World"弹窗跳出来,才真正理解什么叫"让网页动起来"。这里分享几个我踩过坑才掌握的入门要点:
开发环境准备根本不需要复杂配置,用Chrome浏览器+记事本就能开始。但建议安装VS Code,它的智能提示对新手特别友好。记得在首选项里开启"Auto Save",避免忘记保存导致代码丢失——这是我初学时最常犯的低级错误。
变量声明看似简单却藏着陷阱。当年我写的第一个函数是这样的:
function calculateTotal(price, quantity) { total = price * quantity; // 这里漏写了var/let/const return total; }结果这个total变量意外变成了全局变量,引发后续代码的连锁错误。现在教学都会强调用let和const替代var,这是ES6之后的最佳实践。
数据类型转换是初期最容易困惑的部分。尚硅谷课程里那个"0.1+0.2≠0.3"的演示让我记忆犹新。后来做购物车功能时,我特意写了这样的校验逻辑:
const fixFloat = (num) => parseFloat(num.toFixed(2)); console.log(fixFloat(0.1 + 0.2) === 0.3); // 终于得到true2. 核心语法精要:写出健壮的代码
2.1 运算符的隐藏特性
比较运算符==和===的区别老生常谈,但实际开发中更要注意特殊场景:
null == undefined; // true null === undefined; // false NaN === NaN; // false建议在团队中强制使用ESLint配置eqeqeq规则,避免隐式转换引发的bug。
逻辑运算符的短路特性在项目里非常实用。比如处理接口返回数据时:
const userName = response.data?.user?.name || '游客';这种写法比层层if判断简洁得多,也是React组件条件渲染的常用模式。
2.2 流程控制实战技巧
switch语句在尚硅谷的电梯调度案例中展现得很生动。我后来优化过一个状态机逻辑,用对象字面量替代多重switch:
const stateActions = { pending: () => showLoading(), success: (data) => render(data), error: (err) => toast(err.message) }; stateActions[apiStatus]?.();这种模式在Vue/React的状态管理中很常见。
循环语句的优化也值得关注。比如用for...of替代传统for循环处理数组时,能避免索引越界问题。但在遍历DOM集合时,还是要用老式for循环,因为HTMLCollection是动态的。
3. 函数与对象:JavaScript的灵魂所在
3.1 函数的多种面孔
立即执行函数表达式(IIFE)在尚硅谷教程里是用来模拟块级作用域的,现在有了let/const其实可以少用。但在模块化开发中仍有价值:
// 传统IIFE (function() { const privateVar = '内部变量'; })(); // 现代模块模式 const module = (() => { let count = 0; return { increment() { count++ }, getCount() { return count } }; })();箭头函数的this绑定特性在React类组件中救过我。有次写事件回调时:
// 错误写法 class Button extends React.Component { handleClick() { // 这里的this是undefined this.setState({ clicked: true }); } } // 正确写法 class Button extends React.Component { handleClick = () => { this.setState({ clicked: true }); } }3.2 对象与原型深入理解
尚硅谷那个"构造函数-原型对象-实例"的三角关系图示让我茅塞顿开。后来在封装工具库时,我是这样组织代码的:
function Validator(rules) { this.rules = rules; } Validator.prototype.validate = function(value) { return this.rules.every(rule => rule(value)); }; // 使用类语法糖重构 class Validator { constructor(rules) { this.rules = rules; } validate(value) { return this.rules.every(rule => rule(value)); } }对象深拷贝是面试常考题,实际项目中也经常遇到。我的解决方案是:
const deepClone = (obj) => { if (obj === null || typeof obj !== 'object') return obj; const result = Array.isArray(obj) ? [] : {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { result[key] = deepClone(obj[key]); } } return result; };4. DOM与BOM:让网页活起来
4.1 高效DOM操作
尚硅谷的轮播图案例我重写了三遍才彻底掌握。现代开发更推荐用文档片段减少重绘:
const fragment = document.createDocumentFragment(); data.forEach(item => { const li = document.createElement('li'); li.textContent = item.name; fragment.appendChild(li); }); listContainer.appendChild(fragment);事件委托是必须掌握的优化技巧。有次处理动态生成的表格点击时:
// 低效写法 document.querySelectorAll('.delete-btn').forEach(btn => { btn.addEventListener('click', handleDelete); }); // 高效写法 document.getElementById('table').addEventListener('click', (e) => { if (e.target.classList.contains('delete-btn')) { handleDelete(e); } });4.2 现代浏览器API
尚硅谷教程里的定时器相关案例让我理解了异步机制。实际项目中更推荐用requestAnimationFrame做动画:
function animate() { element.style.left = `${position}px`; position += 1; if (position < 100) { requestAnimationFrame(animate); } } requestAnimationFrame(animate);LocalStorage的使用也有讲究。我封装过一个带过期时间的存储工具:
const storage = { set(key, value, expire) { const data = { value, expire: expire ? Date.now() + expire * 1000 : null }; localStorage.setItem(key, JSON.stringify(data)); }, get(key) { const data = JSON.parse(localStorage.getItem(key)); if (!data) return null; if (data.expire && Date.now() > data.expire) { localStorage.removeItem(key); return null; } return data.value; } };5. 高级特性:通往精通的阶梯
5.1 闭包与作用域链
尚硅谷那个经典的计数器闭包案例,我扩展成了模块化开发的基础模式:
const createCounter = () => { let count = 0; return { increment() { count++ }, getCount() { return count }, reset() { count = 0 } }; }; const counter = createCounter(); counter.increment(); console.log(counter.getCount()); // 15.2 Promise与异步编程
回调地狱是每个JS开发者都经历过的痛苦。尚硅谷课程升级后新增的Promise内容非常及时:
// 传统回调 getUser(userId, (user) => { getOrders(user.id, (orders) => { getProducts(orders[0].id, (products) => { console.log(products); }); }); }); // Promise改写 getUser(userId) .then(user => getOrders(user.id)) .then(orders => getProducts(orders[0].id)) .then(products => console.log(products)) .catch(err => console.error(err)); // async/await终极方案 async function displayProducts() { try { const user = await getUser(userId); const orders = await getOrders(user.id); const products = await getProducts(orders[0].id); console.log(products); } catch (err) { console.error(err); } }6. 项目实战:飞机大战重构记
尚硅谷教程最后的飞机大战项目,我用现代前端技术栈重写了一遍。主要改进点:
- 游戏主循环改用requestAnimationFrame:
function gameLoop(timestamp) { if (!lastTime) lastTime = timestamp; const delta = timestamp - lastTime; update(delta); render(); lastTime = timestamp; requestAnimationFrame(gameLoop); }- 对象池模式优化子弹创建:
class BulletPool { constructor(size) { this.pool = Array(size).fill().map(() => new Bullet()); } get() { return this.pool.find(bullet => !bullet.active) || new Bullet(); } reset() { this.pool.forEach(bullet => bullet.active = false); } }- 状态管理使用观察者模式:
class GameEvent { constructor() { this.listeners = {}; } on(type, listener) { if (!this.listeners[type]) { this.listeners[type] = []; } this.listeners[type].push(listener); } emit(type, ...args) { this.listeners[type]?.forEach(fn => fn(...args)); } } const events = new GameEvent(); events.on('enemyDestroyed', (score) => { updateScore(score); });