#函数劫持的使用
函数劫持是一种修改或增强现有函数行为的技术。通过劫持函数,可以在不修改原有函数代码的情况下,增加一些额外的功能,比如日志记录、请求拦截、权限检查等。
#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
可以记录每个请求的时间,帮助进行性能监控和优化。
#总结
函数劫持是一种非常强大的技术,能让我们在不修改原始业务代码的前提下,增强或修改函数行为。通过这种方式,可以实现统一的功能(如日志、错误处理、权限校验等),尤其适用于一些需要全局配置或跨功能模块的场景。