简体   繁体   中英

In which way can i pass through a method call in JavaScript class

Assume we have some classes A and B:

Class A {
    constructor(a) {
       this.a = a;
    };
    showInfo() {
        console.log(this.a)
    };
};

Class B {
    constructor(b) {
        this.b = b;
    };
    printText() {
        console.log('its B!');
    };
};

Then we create an instance of B like this:

const objB = new B(
    new A(3)
);
  1. So now we have objB with its own method inside - printText, and we surely can call it. But what if i want somehow when calling not existing method in objB to make it pass through to encapsulated A class in there and look for invoking this method on him, like this: objB.showInfo() - to give me 3 here ?

  2. Same story, but at this time i want when calling not existing method on A to make it pass through to B outside (like that printText )?

PS Don't wanna use super() and inheritance, just composition and wrapping objects, hope you've got the point.

Just a little warning at the start: this might make your program harder to debug, and it also might be a little complicated for something like this. As others have suggested, you should probably investigate other options which may be simpler and also less in the way of everything else your code does.

Here's the code which provides the functionality:

function makeGetProxy(t){
    return new Proxy(t, {
        get(obj,prop){
            if(prop in t){
                return t[prop];
            }else{
                var keys = Object.keys(obj);
                for (var i = 0; i < keys.length; i++) {
                    var val = t[keys[i]];
                    if(prop in val){
                        return val[prop];
                        // what about a recursive function?
                    }
                }
                return undefined;
            }
        }
    });
}

And one itty bitty change to your constructor in B :

class B {
    constructor(b) {
        this.b = b;
        return makeGetProxy(this);
    };
    printText() {
        console.log('its B!');
    };
};

If you want, you can also do the same to A .

Let's slow down. What just happened? I'll explain.

  1. Since the properties we might request don't already exist, we're going to have to use a getter (see resources) to properly send back the value required. But, since we don't know the property names, we need a Proxy (see resources) to have a "catch-all" kind of get method.

  2. The proxy will check if the property requested prop already exists, and if so, returns it. If it doesn't exist, it checks all of your properties' properties (all of the sub-properties).

  3. The first result it gets, it returns it. This might cause unexpected bugs in your program. If it doesn't find it, it simply returns undefined .

  4. Then, the proxy is generalized into a function for reuse in multiple classes (as you requested).

So, this can get the properties of a class and the properties of a class' properties, but if you need to go further (with your C class that doesn't exist yet), you can use a recursive function. I currently don't have the implementation for that recursive function, but in my head it would comprise mostly of a modified version of the else block in the makeGetProxy function.

Again, be careful with this code. It might get in the way of other things and cause unnecessary difficulty in debugging.

Resources:

This is one way you can do it. It's pretty clunky (having to reference B.prototype , which JS class syntax generally does a good job of hiding from you), and using setPrototypeOf is not recommended as the warning on that docs page shows - but if you really need to have instances of B dynamically delegate whatever object is held in the b property, then this should do the trick.

But I encourage you to rethink your architecture if you really find yourself needing this pattern!

 class A { constructor(a) { this.a = a; }; showInfo() { console.log(this.a) }; }; class B { constructor(b) { this.b = b; Object.setPrototypeOf(B.prototype, this.b); }; printText() { console.log('its B!'); }; }; const objB = new B( new A(3) ); objB.printText(); objB.showInfo();

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