Function.name
属性是可配置的,可以覆盖,但如果我尝试
function foo() {}
Object.defineProperty(foo, 'name', {value: 'bar'})
foo.toString()
仍然显示为"function foo() {}"
,但我期望它是"function bar() {}"
。
你不可能100%可靠地做到这一点。这是因为Function.prototype.toString
的定义,它使用[[SourceText]]内部插槽,它被设置为从用于创建函数的源代码创建的函数。它不使用name
属性。
你也可以尝试重写函数上的toString
,但是如果有人显式地在它上使用Function.prototype.toString
,当然这仍然会失败。
如果你只是想用toString
这样的东西作弊,也许你可以考虑使用Proxy
。
的例子:
const YouWannaChangeName = "modified";
function x(a, b, c) {
return 0;
}
console.log(x.toString());
x = new Proxy(x, {
get(target, prop, receiver) {
if ([Symbol.toPrimitive, "toString"].includes(prop)) {
return function () {
const re = new RegExp(`^function ${target.name}`);
return target.toString().replace(re, `function ${YouWannaChangeName}`);
};
} else {
return target[prop];
}
}
});
console.log(x.toString());
console.log("" + x);
对于本机函数也是有效的。
注意:在2022年之前,浏览器环境不提供任何支持Proxy
的API。事实上,规范还明确指出不应该检测Proxy
。所以我认为这个方法是可靠的。
- 如果你计划部署在服务器端,如Node.js,或特权环境,如浏览器扩展,它将能够被检测到。
- 如果目标函数是自定义函数,确保它没有
configurable: false
和writable: false
)