当前位置: 首页 > news >正文

JavaScript进阶篇——第九章 异常、this 与性能优化全解(终)

目录

1. 异常处理

2. this 指向详解

3. 改变this指向的方法

4. 性能优化技术

5. 防抖与节流对比

6. 复习要点速查表


这是JavaScript最后的技术,也是JavaScript的最后一个章节了。作者本人不厉害,只是整理了一下笔记,方便自己观看和查阅,顺便也能帮到在学JavaScript不想做笔记的人。我可能会时不时观看查阅,看有没有改进的地方。

本文系统介绍了JavaScript的核心概念和技术要点,主要内容包括:

  1. 异常处理机制
  • throw主动抛出异常,推荐使用Error对象
  • try/catch捕获处理异常,finally确保执行关键操作
  • debugger调试技巧
  1. this指向规则
  • 普通函数的this取决于调用者
  • 箭头函数继承定义时的外层this
  • 改变this的三种方法:call/apply/bind
  1. 性能优化技术
  • 防抖(debounce):高频操作只执行最后一次
  • 节流(throttle):限制单位时间内的执行次数
  • 对比分析适用场景和实现原理

文章通过代码示例和对比表格,清晰呈现了各技术要点的核心差异和使用场景,并提供了实用的记忆口诀,帮助开发者快速掌握JavaScript这些关键概念。

1. 异常处理

1.1 throw 抛异常

主动抛出错误,终止程序执行

function divide(a, b) {if (b === 0) {// 抛出错误对象(推荐)throw new Error('除数不能为零');// 也可以抛出简单信息(不推荐)// throw '除数不能为零';}return a / b;
}// 调用
try {divide(10, 0);
} catch (error) {console.log(error.message); // "除数不能为零"
}

核心要点:

  • throw 会立即终止程序执行

  • 推荐使用 Error 对象提供详细错误信息

  • 错误信息包含 message 属性和调用栈

1.2 try/catch/finally 捕获异常

捕获并处理可能的错误,避免程序崩溃

function loadData() {try {// 可能出错的代码const data = JSON.parse(localStorage.getItem('userData'));if (!data) {throw new Error('用户数据不存在');}console.log('数据加载成功:', data);} catch (error) {// 处理错误console.error('错误信息:', error.message);// 可选:显示用户友好的提示alert('加载数据失败,请重试');// 可选:将错误上报到服务器reportError(error);return null;} finally {// 无论是否出错都会执行console.log('数据加载过程结束');// 清理资源等操作}return data;
}

执行流程:

  1. 先执行 try 代码块

  2. 若出错,跳转至 catch 块

  3. finally 块始终执行(即使有 return

1.3 debugger 断点调试

在代码中设置断点进行调试

function calculateTotal(prices) {let total = 0;prices.forEach(price => {debugger; // 在此处暂停total += price * 1.1; // 加10%税费});return total;
}const prices = [100, 200, 300];
console.log(calculateTotal(prices));

调试技巧:

  1. 在开发者工具的 Sources 面板查看

  2. 可查看当前作用域变量

  3. 支持单步执行(Step Over/Into/Out)

  4. 观察调用栈(Call Stack)

2. this 指向详解

2.1 普通函数的 this 指向

规则:谁调用函数,this 就指向谁

// 全局调用 → this = window
function showThis() {console.log(this);
}
showThis(); // window (严格模式下为undefined)// 对象方法 → this = 调用对象
const user = {name: '小明',greet: function() {console.log(`你好,我是${this.name}`);}
};
user.greet(); // "你好,我是小明"// DOM事件 → this = 触发事件的元素
button.addEventListener('click', function() {console.log(this); // <button>元素
});

严格模式影响:

'use strict';
function test() {console.log(this); // undefined
}
test();

2.2 箭头函数的 this 指向

规则:继承外层作用域的 this(定义时确定)

const obj = {name: '小明',traditional: function() {console.log('传统函数:', this.name); // "小明"},arrow: () => {console.log('箭头函数:', this.name); // undefined(外层this)}
};obj.traditional(); // 正常
obj.arrow();       // 异常(this指向window)

适用与不适用场景:

场景适用性说明
对象方法❌ 不适用this 指向外层作用域
DOM事件处理❌ 不适用this 应为DOM元素
原型方法❌ 不适用this 指向外层作用域
回调函数✅ 适用保持外层this
定时器回调✅ 适用保持外层this
// ✅ 适用场景:保持外层this
class SearchComponent {constructor() {this.searchTerm = '';// 箭头函数保持组件实例的thisdocument.getElementById('search').addEventListener('input', (e) => {this.searchTerm = e.target.value;this.performSearch();});}performSearch() {// 使用this.searchTerm}
}

2.3 注意事项

  1. 箭头函数没有自己的this:使用外层this

  2. 无法通过call/apply/bind改变:this在定义时已确定

  3. 多层嵌套时的查找规则:向外层作用域一层层查找this

3. 改变this指向的方法

3.1 call() 方法

立即调用函数,并指定this和参数

function introduce(lang, level) {console.log(`我是${this.name},擅长${lang},水平${level}`);
}const developer = { name: '小明' };// 调用函数,this指向developer
introduce.call(developer, 'JavaScript', '高级');
// "我是小明,擅长JavaScript,水平高级"

参数说明:

  • 第一个参数:this指向的对象

  • 后续参数:函数的参数列表

3.2 apply() 方法

立即调用函数,并指定this和参数数组

function calculate(x, y, z) {return (x + y + z) * this.factor;
}const context = { factor: 2 };// 使用数组传递参数
const result = calculate.apply(context, [10, 20, 30]);
console.log(result); // 120// 实际应用:求数组最大值
const numbers = [5, 2, 8, 4];
const max = Math.max.apply(null, numbers); // 8

与call的区别:

  • call:参数逐个传递(func.call(obj, arg1, arg2))

  • apply:参数以数组传递(func.apply(obj, [arg1, arg2]))

3.3 bind() 方法

创建新函数,永久绑定this(不立即执行)

const user = {name: '小明',greet: function() {console.log(`你好,我是${this.name}`);}
};// 创建绑定函数
const boundGreet = user.greet.bind(user);// 延迟执行
setTimeout(boundGreet, 1000); // 1秒后:"你好,我是小明"// 实际应用:事件处理函数
button.addEventListener('click', user.greet.bind(user));

bind的特点:

  1. 返回新函数,原函数不变

  2. 永久绑定this,无法再次更改

  3. 可预设参数(柯里化)

// 参数预设
function multiply(a, b) {return a * b;
}const double = multiply.bind(null, 2);
console.log(double(5)); // 10 (2 * 5)

4. 性能优化技术

4.1 防抖(debounce)

单位时间内频繁触发,只执行最后一次(搜索框输入)

function debounce(func, delay) {let timer;return function() {const context = this;const args = arguments;clearTimeout(timer); // 清除上次定时器timer = setTimeout(() => {func.apply(context, args);}, delay);};
}// 使用示例
const searchInput = document.getElementById('search');
searchInput.addEventListener('input', debounce(function() {console.log('发送请求:', this.value);
}, 500));

执行过程:

准备开始执行→ 触发→ 取消上次,准备开始执行→ 触发→ 取消上次,准备开始执行→ 触发→ 执行结束

4.2 节流(throttle)

单位时间内频繁触发,只执行一次(滚动事件)

function throttle(func, interval) {let lastTime = 0;return function() {const now = Date.now();const context = this;const args = arguments;if (now - lastTime >= interval) {func.apply(context, args);lastTime = now;}};
}// 使用示例
window.addEventListener('scroll', throttle(function() {console.log('处理滚动:', window.scrollY);
}, 200));

执行过程:

真正开始执行→ 触发→ 执行结束→ 触发→ 执行结束真正开始执行→ 触发→ 执行结束→ 触发→ 执行结束之前已有,取消本次→ 触发,前一个任务还在,取消触发

防抖与节流总结表

性能优化核心原理典型使用场景
防抖 (Debounce)单位时间内频繁触发事件,只执行最后一次搜索框输入、手机号/邮箱验证输入检测
节流 (Throttle)单位时间内频繁触发事件,只执行一次鼠标移动(mousemove)、窗口缩放(resize)、滚动(scroll)

5. 防抖与节流对比

5.1 核心区别

特性防抖节流
执行时机最后一次触发后延迟执行固定时间间隔执行
响应速度延迟响应即时响应
适用事件离散事件(输入、验证)连续事件(滚动、移动)
用户感知等待用户停止操作即时反馈但限频
实现复杂度相对简单相对复杂

5.2 选择指南

  • 使用防抖当

    • 只需最终结果(如搜索建议)

    • 操作成本高(如API请求)

    • 避免中间状态干扰

  • 使用节流当

    • 需要即时反馈(如拖拽效果)

    • 高频事件需要平滑处理(如动画)

    • 保持响应但限制频率

终极选择指南
"输入搜索用防抖,滚动动画用节流"
"高频事件先节流,关键操作后防抖"
"移动端延时要加长,组合使用效果优"
"性能优化无止境,用户体验是王道"

6. 复习要点速查表

异常处理要点

方法作用特点
throw抛出错误终止程序执行
try/catch捕获错误防止程序崩溃
finally最终执行无论是否出错都执行

this指向总结

函数类型this指向是否可改变
普通函数调用者(window/对象)✅ 可改变
箭头函数外层作用域的this❌ 不可改变
构造函数新创建的实例❌ 不可改变
事件处理触发事件的元素✅ 可改变

改变this的方法对比

方法调用时机参数形式返回值
call()立即执行参数列表函数结果
apply()立即执行参数数组函数结果
bind()不执行参数列表新函数

性能优化技术对比

技术核心思想适用场景
防抖只执行最后一次搜索框输入、窗口大小调整结束
节流单位时间只执行一次滚动事件、鼠标移动、高频点击

最佳实践

  1. 异常处理

    • 关键操作使用 try/catch

    • 抛出有意义的错误信息

    • 使用 finally 清理资源

  2. this指向

    • 对象方法使用普通函数

    • 回调函数使用箭头函数

    • 避免在箭头函数中使用 this

  3. 性能优化

    • 输入类事件用防抖

    • 高频触发事件用节流

    • 复杂计算考虑 Web Workers

// 综合示例:安全的API请求
async function fetchData() {try {const response = await fetch('https://api.example.com/data');const data = await response.json();return processData(data);} catch (error) {console.error('请求失败:', error);showErrorToast('数据加载失败');throw error; // 继续向上抛出} finally {hideLoadingSpinner();}
}

记忆口诀
"异常处理三步走,try/catch/finally"
"this指向看调用,箭头函数看外层"
"call/apply立即调,bind绑定返新函"
"防抖节流性能优,高频操作不发愁"

http://www.dtcms.com/a/285953.html

相关文章:

  • 14.链路聚合技术
  • 量化交易如何查询CFD指数实时行情
  • postman接口测试,1个参数有好几个值的时候如何测试比较简单快速?
  • IP协议深入理解
  • 20250718-4-Kubernetes 应用程序生命周期管理-Pod对象:实现机制_笔记
  • 如何保证缓存数据的一致性:数据库和缓存数据一致性,本地缓存和Redis缓存怎么保证数据一致性
  • Netty封装Websocket并实现动态路由
  • Spring Boot 应用优雅停机与资源清理:深入理解关闭钩子
  • 比特币技术简史 第四章:挖矿机制 - 挖矿算法、难度调整与矿池
  • 在ajax中什么时候需要将返回值类型做转换
  • Excel基础:格式化
  • 产品需求文档(PRD)格式全解析:从 RP 到 Word 的选择与实践
  • 2023 年 3 月青少年软编等考 C 语言八级真题解析
  • 回归预测 | MATLAB实现DBO-BP蜣螂算法优化BP神经网络多输入单输出回归预测
  • 借助AI学习开源代码git0.7之三git-init-db
  • MyBatis-Flex代码生成
  • ARINC818协议详解
  • KRaft 角色状态设计模式:从状态理解 Raft
  • 美创科技建设项目被评为中国信通院医疗领域“磐安”优秀案例
  • A33-vstar报错记录:ERROR: build kernel Failed
  • 北京-4年功能测试2年空窗-报培训班学测开-第五十四天
  • (笔记+作业)第五期书生大模型实战营---L2G2000 GraphGen:训练数据合成实践
  • U盘运维笔记
  • 前端-CSS盒模型
  • 源鉴SCA4.9︱多模态SCA引擎重磅升级,开源风险深度治理能力再次进阶
  • world models and Human–Object Interaction (HOI)
  • Ubuntu locale命令介绍(查询和设置当前用户的语言、国家/地区以及字符编码等环境设置)
  • Windows 安装WSL +Docker 部署通义千问大模型(同步解决Ubuntu启动命令闪退)
  • 注册表单案例
  • Android性能优化之内存优化