函数劫持的使用

发布于:

#函数劫持的使用

函数劫持是一种修改或增强现有函数行为的技术。通过劫持函数,可以在不修改原有函数代码的情况下,增加一些额外的功能,比如日志记录、请求拦截、权限检查等。

#1. 劫持 console.log

最简单的一种函数劫持方式是重写 console.log,改变其输出行为。下面的示例演示了如何在不修改 console.log 原有实现的前提下,对某些特定情况的输出进行干预。

#示例代码:

js
// 保存原有的 console.log const _console_log = console.log // 重写 console.log console.log = function (...args) { const message = args[0] || '' // 如果传入的日志消息为 '测试',则输出警告信息 if (message === '测试') { console.warn('啦啦啦') return // 阻止原 console.log 的调用 } // 默认情况下调用原有的 console.log _console_log.apply(console, args) } // 测试新的 console.log 行为 console.log('测试') // 输出: '啦啦啦' console.log('Hello, world!') // 输出: 'Hello, world!'

#解释:

  • console.log 被重写,条件判断决定了某些特定日志是否会被拦截并修改。
  • 如果传入的参数是 '测试',我们就输出一个警告信息(console.warn),而不调用原 console.log
  • 否则,使用 apply 调用原始的 console.log 方法,保持其他日志输出不变。

#2. 劫持并重写 fetch 来实现拦截器

除了同步函数,异步函数(如 fetch)也可以被劫持。在这个示例中,我们劫持了 fetch 函数,使得每次请求的响应被拦截后,先打印一条“响应成功”的信息。这样可以方便地在不修改原有业务代码的情况下,进行统一的处理(例如日志记录、性能监控、请求失败上报等)。

#示例代码:

js
// 原始的 fetch 请求函数 function fetchData() { fetch('https://jsonplaceholder.typicode.com/posts') .then(res => res.json()) .then(console.log) // 输出响应的结果 } // 调用原始 fetch 函数 fetchData() // 保存原始的 window.fetch const _fetch = window.fetch // 重写 window.fetch window.fetch = function (...args) { // 调用原始的 fetch 请求并拦截其返回的 promise const promise = _fetch.apply(window, args).then(res => { // 请求成功后,输出提示信息 console.log('响应成功') return res // 返回原始响应 }) return promise // 返回被拦截的 Promise 对象 } // 再次调用 fetchData,触发新的 fetch 行为 fetchData()

#解释:

  • 我们首先保存了原有的 fetch 函数,并在其上进行重写。
  • 当调用 fetch 时,我们先让其继续执行原始请求(使用 apply 调用原 fetch),并在 then 中对响应进行拦截和处理。我们打印了一条成功响应的日志,然后返回原始的响应对象。
  • 这样一来,所有的 fetch 请求都能在处理完响应后执行一些自定义逻辑(如日志、上报等),而不会影响原有业务逻辑。

#使用场景:

  • 请求拦截:通过劫持 fetch 函数,可以添加请求头、修改请求体、记录请求日志等。
  • 响应拦截:可以在响应返回后做统一的处理,比如根据状态码判断请求是否成功、统一处理错误信息等。
  • 性能监控:劫持 fetch 可以记录每个请求的时间,帮助进行性能监控和优化。

#总结

函数劫持是一种非常强大的技术,能让我们在不修改原始业务代码的前提下,增强或修改函数行为。通过这种方式,可以实现统一的功能(如日志、错误处理、权限校验等),尤其适用于一些需要全局配置或跨功能模块的场景。