Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。
题目 实现spyOn 题目描述 如果你写过单元测试的话,一定很熟悉
Spy
的用法。
请自己实现一个spyOn(object, methodName) ,类似于 jest.spyOn()。
以下是spyOn
需要完成的内容。
- spy被调用的时候,原来的method也需要被调用。
- spy需要又一个
calls
数组,数组中含有所有调用的参数
以下代码说明了一切。
const obj = {
data: 1,
increment(num) {
this.data += num
}
}
const spy = spyOn(obj, 'increment')
obj.increment(1)
console.log(obj.data) // 2
obj.increment(2)
console.log(obj.data) // 4
console.log(spy.calls)
// [ [1], [2] ]
思路 题目要求监听给定目标的某一函数的调用,并且将参数收集起来,看到该需求的时候脑子里第一时刻想的就是vue2使用的
Object.defineProperty()
,也就是setter,getter,但是getter好像并不能收集参数,于是更进一步,vue3使用的proxy
。
我的实现 核心思想就是通过proxy来监听指定函数,通过handler.apply()来监听函数调用。
function spyOn(obj, methodName) {
const calls = [];
const proxyedFn = new Proxy(obj[methodName], {
apply: (target, thisArg, args) => {
//target:调用函数
//thisArg: 被调用时的上下文对象。即this指向
//args: 被调用时的参数数组
calls.push(args);
return target.apply(thisArg, args);
}
})
//记得覆盖原始方法
obj[methodName] = proxyedFn;
return { calls };
}
其它实现 看完评论区的答案,感觉我好像想的复杂了,直接覆盖就行了...
function spyOn(obj, methodName) {
if(!obj[methodName] || typeof obj[methodName] != 'function') throw Error('invalid obj.methodName')
const calls = [];
const originFn = obj[methodName]
obj[methodName] = (...args) => {
calls.push(args);
return originFn.apply(this, args);
}
return { calls }
}