【问题标题】:Why do ES6's Proxy doesn't work when used inside a method of class?为什么在类方法中使用 ES6 的 Proxy 不起作用?
【发布时间】:2021-05-05 17:40:29
【问题描述】:

在类的方法内部使用时,逻辑不起作用,但如果我在函数式样式中使用它,则在外部起作用。

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())

我应该怎么做才能使它在一个类中工作?

【问题讨论】:

  • 你想完成什么?
  • 我认为你需要在创建类之后创建代理。
  • @PatrickRoberts 什么都没有。只是用一个类来试验 ES6 Proxy。
  • @luekbaja 看代码可以看到我在类初始化后创建了代理,
  • 我不明白这个问题。 什么不起作用?

标签: javascript es6-proxy


【解决方案1】:

“问题”不在于代理 - 所有呼叫都已通过它。问题是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, thisArg, 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())

捕获变量中的值

这通过在创建时使用const obj = this.object 捕获this.object 的值并稍后仅使用obj 来避免使用this,这将始终具有相同的值:

class Hook {
    constructor(object) {
        this.object = object;
    }

    toStringProperty() {
        const obj = this.object; //<--- capture 
        const handler = {
            apply: function (target, thisArg, args){
                if (thisArg === Function.prototype.toString) {
                    return 'function toString() { [native code] }'
                }

                if (thisArg === obj) { //<--- use
                    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())

【讨论】:

    猜你喜欢
    • 2021-07-24
    • 2016-12-05
    • 1970-01-01
    • 2018-10-10
    • 2023-03-03
    • 2019-07-18
    • 1970-01-01
    • 1970-01-01
    • 2013-01-22
    相关资源
    最近更新 更多