-1

I want to pass the Class instance itself into a function using function.apply and I use this keyword for the first pram of function.apply; however, the function sees WIndow Object instead Class instance when run a validation logic.

class T {
    transform(handler = {}) {
        const newHandler = {};

        const methods = Object.getOwnPropertyNames(handler);

        for (const method of methods) {
            newHandler[method] = (...args) => {
                return handler[method].apply(this, args || []);
            }
        }

        return newHandler;
    }
}

const transformer = new T();

transformer.name = "John"

const transformed = transformer.transform({
    printName: () => {
        if("toString" in this && this.toString() == "[object Window]") {
            console.log("this is Window")
        } else {   
            console.log(`You are ${this.name}`);
        }
    }
});

transformed.printName();
jeffbRTC
  • 1,941
  • 10
  • 29
  • Using the arrow syntax to define a class method is not valid javascript as far as I understand - `transform = (handler = {}) => {...` ... yet works and does not seem to be the cause of your problem – Stuart Jun 17 '21 at 21:00
  • Understand the limitations of arrow functions. They aren't just a drop-in replacement for all functions in all scenarios. – Kevin B Jun 17 '21 at 21:06
  • @Stuart I've changed it to `transform(handler = {}) { .. ` but it still doesn't work... – jeffbRTC Jun 17 '21 at 21:07
  • @KevinB Of course, but changing it to non-arrow yields same result – jeffbRTC Jun 17 '21 at 21:08
  • I've edited to the question to reflect the change.. – jeffbRTC Jun 17 '21 at 21:09
  • 1
    I get "You are John" when i replace the arrow function in printName with a normal one. The one .apply is being used on. you can't change the `this` of an arrow function, so in cases where you need to, you need to not use an arrow function. – Kevin B Jun 17 '21 at 21:10
  • @KevinB Oh, I thought I have to replace only `transform(handler = {}) { .. ` one.. – jeffbRTC Jun 17 '21 at 21:11

1 Answers1

-1

It likely has to deal with how the Lexical Scope works with arrow functions.

https://medium.com/hackernoon/javascript-es6-arrow-functions-and-lexical-this-f2a3e2a5e8c4

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

The arrow function inside of the transformer.transform function seems to be binding to window, before it is added to the transformer. By changing it to use the function keyword it no longer binds it's this to window and displays the desired result.

class T {
    transform = (handler = {}) => {
        const newHandler = {};

        const methods = Object.getOwnPropertyNames(handler);

        for (const method of methods) {
            newHandler[method] = handler[method].bind(this);
        }

        return newHandler;
    }
}

const transformer = new T();

transformer.name = "John"

const transformed = transformer.transform({
    printName: function () {
        if(this === window) {
            console.log("this is Window")
        } else {   
            console.log(`You are ${this.name}`);
        }
    }
});

transformed.printName();
  • This is not what my code is. My code is a method transformer and I didn't add all the logic. You basically removed the ability to do transformation by `handler[method].bind(this); .. ` – jeffbRTC Jun 17 '21 at 20:53
  • this answer did at least change the correct arrow function to a normal one – Kevin B Jun 17 '21 at 21:12
  • I actually prefer this answer to your code with just the arrow function replaced, it unwraps the handler and just returns it, bound correctly. – Kevin B Jun 17 '21 at 21:14
  • @jeffbRTC Sounds like an interesting project! Can you help me understand what you mean by removed the ability to do transformation (if you are able to share the information and it is not in a project that cannot be shared!)? I was under the assumption that `(...args) => fn.apply(this, args)` was equivalent to `fn.bind(this)`, I would love to learn more! – Seth MacPherson Jun 18 '21 at 13:20