我想拦截函数调用,发现代理可以使用 apply 方法来实现这一点,如 MDN 所示。但是我很快发现传递给函数的参数不会被拦截,因此如果您的参数可以是表达式,例如标记模板文字的情况,例如 apply 方法不会拦截标记模板的执行,并且它`s 表达式,为什么会这样?除了创建包装函数之外还有什么方法可以做到这一点?我认为参数应该被拦截,对我来说,这也像是代理实现中的一个错误。
// create tagged template function
function template(strings, ...keys) {
console.log("tmp fn");
return (...values) => {
const dict = values[values.length - 1] || {};
const result = [strings[0]];
keys.forEach((key, i) => {
const value = Number.isInteger(key) ? values[key] : dict[key];
result.push(value, strings[i + 1]);
});
return result.join("");
};
}
// Trapping a function call with proxy
const taggedTemplate = new Proxy(template, {
apply(target, thisArg, argArray) {
console.log("apply");
return target(...argArray)
}
});
// some fn for the template
function Num() {
console.log("Not intercepted Num() call")
return 5
};
// use template
taggedTemplate`my fav number is ${Num()}`
我想拦截函数调用,发现代理可以做到这一点
太复杂了。您所需要的只是一个包装函数:
// Trapping a function call with another function
const taggedTemplate = (...argArray) => {
console.log("apply");
return target(...argArray);
};
代理在这里没有实现任何其他功能。
我很快发现传递给函数的参数没有被拦截。这是为什么?
因为只有
taggedTemplate
是代理(或包装函数),并且当调用特定的 apply
函数对象时,会触发 taggedTemplate
陷阱。 Num()
不涉及任何代理。表达taggedTemplate`my fav number is ${Num()}`
与做没有什么不同
const value = Num();
taggedTemplate`my fav number is ${value}`
有什么办法可以做到吗?
没有。