微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么 ES6 的 Proxy 在类的方法中使用时不起作用?

如何解决为什么 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 举报,一经查实,本站将立刻删除。