1. JavaScript学习笔记:从基础到实战
作为一名前端开发者,我经常需要记录JavaScript学习过程中的关键知识点和实用技巧。这份笔记是我多年工作经验的积累,涵盖了从基础语法到高级特性的全方位内容。JavaScript作为现代Web开发的基石,掌握它的核心概念和实际应用对每个开发者都至关重要。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. JavaScript基础语法精要
2.1 变量与数据类型
JavaScript中的变量声明经历了从var到let/const的演进。在实际开发中,我强烈建议:
- 优先使用const声明不会改变的常量
- 使用let声明需要重新赋值的变量
- 避免使用var,因为它存在变量提升和函数作用域的问题
javascript复制// 好的实践
const PI = 3.14;
let count = 0;
// 不好的实践
var name = "old";
JavaScript有7种原始数据类型:undefined、null、boolean、number、string、symbol和bigint。理解类型转换特别重要:
javascript复制// 类型转换示例
console.log(1 + "2"); // "12" (字符串拼接)
console.log("3" * 2); // 6 (自动转换为数字)
2.2 函数与作用域
函数是JavaScript的一等公民。现代JS开发中,箭头函数因其简洁的语法和词法this绑定而广受欢迎:
javascript复制// 传统函数
function add(a, b) {
return a + b;
}
// 箭头函数
const multiply = (a, b) => a * b;
作用域链和闭包是JS的核心概念。闭包允许函数访问并记住其词法作用域,即使函数在其词法作用域之外执行:
javascript复制function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
3. DOM操作与事件处理
3.1 高效DOM操作
DOM操作是前端开发中最耗性能的部分之一。我总结了几个优化技巧:
- 批量修改DOM时,使用文档片段(document fragment)
- 避免在循环中直接操作DOM
- 使用事件委托减少事件监听器数量
javascript复制// 使用文档片段
const fragment = document.createDocumentFragment();
for(let i = 0; i < 100; i++) {
const div = document.createElement('div');
fragment.appendChild(div);
}
document.body.appendChild(fragment);
// 事件委托示例
document.getElementById('parent').addEventListener('click', function(e) {
if(e.target.classList.contains('child')) {
// 处理子元素点击
}
});
3.2 iframe交互实践
处理iframe与父页面交互是常见需求。以下是实现iframe关闭并刷新父页面的可靠方法:
javascript复制// 在父页面
const iframe = document.createElement('iframe');
iframe.src = 'child.html';
document.body.appendChild(iframe);
// 在iframe内部
window.parent.postMessage('close-iframe', '*');
// 父页面监听消息
window.addEventListener('message', function(e) {
if(e.data === 'close-iframe') {
iframe.remove();
location.reload(); // 刷新父页面
}
});
4. 现代JavaScript特性
4.1 ES6+核心特性
解构赋值、扩展运算符和模板字符串极大提高了代码可读性:
javascript复制// 解构赋值
const [first, second] = [1, 2];
const {name, age} = {name: 'Alice', age: 25};
// 扩展运算符
const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4]; // [1, 2, 3, 4]
// 模板字符串
const greeting = `Hello, ${name}! You are ${age} years old.`;
4.2 异步编程演进
从回调地狱到Promise再到async/await,JavaScript的异步处理越来越优雅:
javascript复制// 回调地狱
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log(finalResult);
});
});
});
// Promise链
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => console.log(finalResult))
.catch(error => console.error(error));
// async/await
async function foo() {
try {
const result = await doSomething();
const newResult = await doSomethingElse(result);
const finalResult = await doThirdThing(newResult);
console.log(finalResult);
} catch(error) {
console.error(error);
}
}
5. 实用工具函数集合
5.1 常用验证函数
javascript复制// 验证URL有效性
function isValidUrl(url) {
try {
new URL(url);
return true;
} catch {
return false;
}
}
// 判断字符串包含
function contains(str, substr) {
return str.includes(substr);
}
// 获取当前年份
function getCurrentYear() {
return new Date().getFullYear();
}
5.2 数组高级操作
数组方法是JS开发中最常用的工具之一:
javascript复制const numbers = [1, 2, 3, 4, 5];
// map转换
const doubled = numbers.map(n => n * 2);
// filter过滤
const evens = numbers.filter(n => n % 2 === 0);
// reduce聚合
const sum = numbers.reduce((acc, n) => acc + n, 0);
// sort排序
const sorted = [...numbers].sort((a, b) => b - a);
6. 浏览器API实战技巧
6.1 History API应用
现代单页应用(SPA)离不开History API:
javascript复制// 添加历史记录
history.pushState({page: 1}, "Title 1", "?page=1");
// 监听popstate事件
window.addEventListener('popstate', function(event) {
console.log("Location changed to", location.href);
});
// 返回上一页
function goBack() {
window.history.back();
}
6.2 检测浏览器行为
检测微信内置浏览器的滑动返回行为:
javascript复制let startX = 0;
document.addEventListener('touchstart', (e) => {
startX = e.touches[0].pageX;
});
document.addEventListener('touchmove', (e) => {
const moveX = e.touches[0].pageX;
if(moveX - startX > 50) {
console.log('检测到滑动返回手势');
// 执行相应操作
}
});
7. 性能优化与调试
7.1 内存管理
JavaScript的垃圾回收是自动的,但仍有内存泄漏的风险:
- 意外的全局变量
- 遗忘的定时器或回调
- DOM引用未清除
- 闭包滥用
javascript复制// 内存泄漏示例
function leakMemory() {
this.array = new Array(1000000).fill('*');
// 忘记清除
}
// 正确的做法
function noLeak() {
const array = new Array(1000000).fill('*');
// 使用后自动回收
}
7.2 调试技巧
Chrome开发者工具是调试JavaScript的利器:
- 使用
debugger语句设置断点 - 利用Console API输出调试信息
- 性能面板分析运行时性能
- 内存面板检查内存使用情况
javascript复制// 条件调试
if(someCondition) {
debugger; // 执行到这里会暂停
}
// 控制台输出
console.time('timer');
// 一些操作
console.timeEnd('timer'); // 输出执行时间
8. 安全最佳实践
8.1 XSS防护
跨站脚本攻击(XSS)是最常见的安全威胁之一:
javascript复制// 不安全的做法 - 直接插入HTML
element.innerHTML = userInput; // 危险!
// 安全的做法 - 文本内容
element.textContent = userInput;
// 或者使用DOMPurify等库净化HTML
const clean = DOMPurify.sanitize(userInput);
element.innerHTML = clean;
8.2 CSRF防护
跨站请求伪造(CSRF)防护措施:
- 使用SameSite Cookie属性
- 实现CSRF令牌
- 验证Origin/Referer头部
javascript复制// 服务端设置SameSite Cookie
Set-Cookie: sessionid=123; SameSite=Strict; Secure
// 客户端CSRF令牌
fetch('/api/data', {
method: 'POST',
headers: {
'X-CSRF-Token': getCSRFToken()
}
});
9. 模块化与工程化
9.1 ES模块系统
现代JavaScript开发使用ES模块:
javascript复制// math.js
export function add(a, b) {
return a + b;
}
export const PI = 3.14159;
// app.js
import { add, PI } from './math.js';
console.log(add(PI, 2));
9.2 打包工具配置
Webpack是现代前端项目的标配:
javascript复制// webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
}
]
}
};
10. 高级概念与模式
10.1 设计模式应用
JavaScript中常用的设计模式:
- 模块模式
- 观察者模式
- 工厂模式
- 单例模式
javascript复制// 模块模式
const counterModule = (function() {
let count = 0;
return {
increment() {
count++;
},
getCount() {
return count;
}
};
})();
// 观察者模式
class EventEmitter {
constructor() {
this.events = {};
}
on(event, listener) {
(this.events[event] || (this.events[event] = [])).push(listener);
}
emit(event, ...args) {
(this.events[event] || []).forEach(listener => listener(...args));
}
}
10.2 函数式编程
JavaScript支持函数式编程范式:
javascript复制// 纯函数
function pureAdd(a, b) {
return a + b;
}
// 高阶函数
function multiplyBy(factor) {
return function(number) {
return number * factor;
};
}
const double = multiplyBy(2);
console.log(double(5)); // 10
// 函数组合
const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
const add1 = x => x + 1;
const square = x => x * x;
const addThenSquare = compose(square, add1);
console.log(addThenSquare(2)); // 9
11. 实战项目经验
11.1 表单验证库实现
一个简单的表单验证库核心逻辑:
javascript复制class Validator {
constructor(rules) {
this.rules = rules;
this.errors = {};
}
validate(formData) {
this.errors = {};
Object.entries(this.rules).forEach(([field, fieldRules]) => {
fieldRules.forEach(rule => {
if(!rule.validator(formData[field])) {
this.errors[field] = this.errors[field] || [];
this.errors[field].push(rule.message);
}
});
});
return Object.keys(this.errors).length === 0;
}
}
// 使用示例
const validator = new Validator({
username: [
{
validator: val => val.length >= 3,
message: '用户名至少3个字符'
}
],
email: [
{
validator: val => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),
message: '请输入有效的邮箱地址'
}
]
});
11.2 图片懒加载组件
性能优化的图片懒加载实现:
javascript复制class LazyLoad {
constructor(selector) {
this.images = document.querySelectorAll(selector);
this.init();
}
init() {
if('IntersectionObserver' in window) {
this.observeWithIO();
} else {
this.observeWithScroll();
}
}
observeWithIO() {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if(entry.isIntersecting) {
this.loadImage(entry.target);
observer.unobserve(entry.target);
}
});
});
this.images.forEach(img => observer.observe(img));
}
observeWithScroll() {
const onScroll = () => {
this.images.forEach(img => {
if(this.isInViewport(img)) {
this.loadImage(img);
}
});
};
window.addEventListener('scroll', onScroll);
onScroll(); // 初始检查
}
isInViewport(element) {
const rect = element.getBoundingClientRect();
return (
rect.top <= window.innerHeight &&
rect.bottom >= 0
);
}
loadImage(img) {
const src = img.dataset.src;
if(src) {
img.src = src;
img.removeAttribute('data-src');
}
}
}
// 使用
new LazyLoad('img[data-src]');
12. 常见问题解决方案
12.1 跨域请求处理
现代前端处理跨域的几种方式:
- CORS (服务端设置响应头)
- JSONP (仅限GET请求)
- 代理服务器
- WebSocket
javascript复制// CORS示例
fetch('https://api.example.com/data', {
method: 'GET',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => console.log(data));
// JSONP实现
function jsonp(url, callback) {
const script = document.createElement('script');
const callbackName = 'jsonp_callback_' + Math.round(100000 * Math.random());
window[callbackName] = function(data) {
delete window[callbackName];
document.body.removeChild(script);
callback(data);
};
script.src = url + (url.indexOf('?') >= 0 ? '&' : '?') + 'callback=' + callbackName;
document.body.appendChild(script);
}
12.2 性能监控
前端性能数据采集:
javascript复制// 关键性能指标
const perfData = {
dns: performance.timing.domainLookupEnd - performance.timing.domainLookupStart,
tcp: performance.timing.connectEnd - performance.timing.connectStart,
ttfb: performance.timing.responseStart - performance.timing.requestStart,
domReady: performance.timing.domContentLoadedEventEnd - performance.timing.navigationStart,
loadTime: performance.timing.loadEventEnd - performance.timing.navigationStart
};
// 发送到监控系统
navigator.sendBeacon('/perf-log', JSON.stringify(perfData));
// 资源加载监控
const resources = performance.getEntriesByType('resource');
resources.forEach(resource => {
console.log(`${resource.name} 加载耗时: ${resource.duration}ms`);
});
13. 现代框架核心原理
13.1 虚拟DOM实现
理解虚拟DOM有助于更好地使用现代框架:
javascript复制class VNode {
constructor(tag, props, children) {
this.tag = tag;
this.props = props || {};
this.children = children || [];
}
render() {
const el = document.createElement(this.tag);
// 设置属性
Object.entries(this.props).forEach(([key, value]) => {
el.setAttribute(key, value);
});
// 渲染子节点
this.children.forEach(child => {
const childNode = child instanceof VNode
? child.render()
: document.createTextNode(child);
el.appendChild(childNode);
});
return el;
}
}
// 使用示例
const vdom = new VNode('div', {id: 'app'}, [
new VNode('h1', null, ['Hello World']),
new VNode('p', {class: 'desc'}, ['This is a virtual DOM example'])
]);
document.body.appendChild(vdom.render());
13.2 响应式系统
Vue等框架的核心响应式原理:
javascript复制class Dep {
constructor() {
this.subscribers = [];
}
depend() {
if(Dep.target && !this.subscribers.includes(Dep.target)) {
this.subscribers.push(Dep.target);
}
}
notify() {
this.subscribers.forEach(sub => sub());
}
}
Dep.target = null;
function observe(obj) {
Object.keys(obj).forEach(key => {
let value = obj[key];
const dep = new Dep();
Object.defineProperty(obj, key, {
get() {
dep.depend();
return value;
},
set(newVal) {
if(newVal !== value) {
value = newVal;
dep.notify();
}
}
});
});
}
function autorun(fn) {
Dep.target = fn;
fn();
Dep.target = null;
}
// 使用示例
const state = { count: 0 };
observe(state);
autorun(() => {
console.log(`Count changed to ${state.count}`);
});
state.count++; // 自动触发日志输出
14. 测试与质量保证
14.1 单元测试实践
使用Jest进行JavaScript单元测试:
javascript复制// math.js
function sum(a, b) {
return a + b;
}
function divide(a, b) {
if(b === 0) throw new Error('Division by zero');
return a / b;
}
module.exports = { sum, divide };
// math.test.js
const { sum, divide } = require('./math');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
test('throws error when dividing by zero', () => {
expect(() => divide(1, 0)).toThrow('Division by zero');
});
14.2 E2E测试方案
使用Cypress进行端到端测试:
javascript复制// login.spec.js
describe('Login Test', () => {
it('should login successfully', () => {
cy.visit('/login');
cy.get('#username').type('testuser');
cy.get('#password').type('password123');
cy.get('form').submit();
cy.url().should('include', '/dashboard');
cy.contains('Welcome, testuser');
});
it('should show error for invalid credentials', () => {
cy.visit('/login');
cy.get('#username').type('wronguser');
cy.get('#password').type('wrongpass');
cy.get('form').submit();
cy.contains('Invalid username or password');
});
});
15. 持续学习资源
15.1 推荐学习路径
-
基础阶段:
- MDN JavaScript指南
- 《JavaScript高级程序设计》
- 《你不知道的JavaScript》系列
-
进阶阶段:
- 《JavaScript设计模式》
- 《函数式编程指南》
- 《深入理解ES6》
-
框架与工程化:
- Vue/React官方文档
- Webpack/Babel深入
- Node.js实战
15.2 实用工具与库
-
开发工具:
- VS Code + ESLint + Prettier
- Chrome DevTools
- Postman/Insomnia
-
实用库:
- Lodash (工具函数)
- Axios (HTTP客户端)
- Day.js (日期处理)
- Ramda (函数式编程)
-
测试工具:
- Jest (单元测试)
- Cypress (E2E测试)
- Storybook (UI组件开发)
在实际项目中,我发现持续记录学习笔记并定期回顾是提升JavaScript技能最有效的方法之一。每当遇到新问题或学习新技术时,我都会更新这份笔记,确保知识体系与时俱进。
