如何解决为什么 ES6 的 Proxy 在类的方法中使用时不起作用?
在类的方法内部使用时,逻辑不起作用,但如果我以函数式风格使用它,则逻辑不起作用。
class Hook {
constructor(object) {
this.object = object;
}
toStringproperty() {
const handler = {
apply: function (target,thisArg,args){
if (thisArg === Function.prototype.toString) {
return 'function toString() { [native code] }'
}
if (thisArg === this.object) {
return "Hooked String"
}
return target.apply(thisArg,args)
}
}
Function.prototype.toString = new Proxy(Function.prototype.toString,handler)
}
}
let hook = new Hook(HTMLAudioElement);
hook.toStringproperty();
// Interesting enough this when called (I use Devtools) logs Proxy Object itself but only happen if I use a Class
console.log(Function.prototype.toString)
console.log(HTMLAudioElement.toString())
我应该怎么做才能让它在类中工作?
解决方法
“问题”不在于代理——所有调用都已经通过它。问题是 how the this
keyword works 的古老细节。简而言之,它是在调用时确定的,因此 this.object
将具有不同的含义,具体取决于函数的调用时间和调用方式。在这种情况下,this
的值是“丢失”not unlike how you lose it in a callback。
如果你需要具体参考某事,你有几个选择
词法绑定 this
使用箭头函数 () => {}
一个箭头函数uses the this
value of the enclosing context 在创建时,所以它在调用时不会改变:
class Hook {
constructor(object) {
this.object = object;
}
toStringProperty() {
const handler = {
apply: (target,thisArg,args) => { //<--- arrow function
if (thisArg === Function.prototype.toString) {
return 'function toString() { [native code] }'
}
if (thisArg === this.object) {
return "Hooked String"
}
return target.apply(thisArg,args)
}
}
Function.prototype.toString = new Proxy(Function.prototype.toString,handler)
}
}
let hook = new Hook(HTMLAudioElement);
hook.toStringProperty();
// Interesting enough this when called (I use Devtools) logs Proxy Object itself but only happen if I use a Class
console.log(Function.prototype.toString)
console.log(HTMLAudioElement.toString())
使用Function#bind
手动绑定this
这对于箭头函数来说基本上是多余的,但仍然是一个选项:
class Hook {
constructor(object) {
this.object = object;
}
toStringProperty() {
const handler = {
apply: function (target,args){
if (thisArg === Function.prototype.toString) {
return 'function toString() { [native code] }'
}
if (thisArg === this.object) {
return "Hooked String"
}
return target.apply(thisArg,args)
}.bind(this) //<--- bind `this` from creation time
}
Function.prototype.toString = new Proxy(Function.prototype.toString,handler)
}
}
let hook = new Hook(HTMLAudioElement);
hook.toStringProperty();
// Interesting enough this when called (I use Devtools) logs Proxy Object itself but only happen if I use a Class
console.log(Function.prototype.toString)
console.log(HTMLAudioElement.toString())
捕获变量中的值
这通过在创建时使用 this
捕获 this.object
的值并稍后使用始终具有相同值的 const obj = this.object
来避免使用 obj
:
class Hook {
constructor(object) {
this.object = object;
}
toStringProperty() {
const obj = this.object; //<--- capture
const handler = {
apply: function (target,args){
if (thisArg === Function.prototype.toString) {
return 'function toString() { [native code] }'
}
if (thisArg === obj) { //<--- use
return "Hooked String"
}
return target.apply(thisArg,handler)
}
}
let hook = new Hook(HTMLAudioElement);
hook.toStringProperty();
// Interesting enough this when called (I use Devtools) logs Proxy Object itself but only happen if I use a Class
console.log(Function.prototype.toString)
console.log(HTMLAudioElement.toString())
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。