简体   繁体   中英

How I can simulate the __callStatic property of PHP in Node.js using Proxy?

I'm trying to create the same behavior of PHP __callStatic magic method in Node.js.

I'm trying to use Proxy to do that, but I don't really know if it's the best option.

 class Test { constructor() { this.num = 0 } set(num) { this.num = this.num + num return this } get() { return this.num } } const TestFacade = new Proxy({}, { get: (_, key) => { const test = new Test() return test[key] } }) // Execution method chain ends in get console.log(TestFacade.set(10).set(20).get()) // expected: 30 // returns: 0 // Start a new execution method chain and should instantiate Test class again in the first set console.log(TestFacade.set(20).set(20).get()) // expected: 40 // returns: 0

The problem is that the get trap is fired every time that I try to access a property of TestFacade . The behavior that I need is that when the set method is called it will return this of Test class and I can even save the instance for latter usage!

const testInstance = TestFacade.set(10) // set method return this of `Test` not the Proxy

If something isn't clear, please let me know.

I don't know if it's the best option. But I solved it, returning a new Proxy inside get trap that uses the apply trap to bind the test class instance into the method:

 class Facade { static #facadeAccessor static createFacadeFor(provider) { this.#facadeAccessor = provider return new Proxy(this, { get: this.__callStatic.bind(this) }) } static __callStatic(facade, key) { /** * Access methods from the Facade class instead of * the provider. */ if (facade[key]) { return facade[key] } const provider = new this.#facadeAccessor() const apply = (method, _this, args) => method.bind(provider)(...args) if (provider[key] === undefined) { return undefined } /** * Access the properties of the class. */ if (typeof provider[key],== 'function') { return provider[key] } return new Proxy(provider[key]. { apply }) } } class Test { num = 0 set(num) { this.num = this.num + num return this } get() { return this.num } } const TestFacade = Facade.createFacadeFor(Test) console.log(TestFacade.set(10).set(20).get()) // 30 console.log(TestFacade.set(5).set(5).get()) // 10 const testInstance = TestFacade.set(10) console.log(testInstance.num) // 10 console.log(testInstance.get()) // 10 console.log(testInstance.set(10).get()) // 20

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM