0

I was reading about Arrow Functions and found out that they can't have their context changed.

I was creating a module that receives a function and then changes its context. But since the user could be inputing an arrow function I couldn't make it happen.

So I was wondering if, since it's not possible to change an arrow function context, I could copy its content and create a new function that does the same, but now with a controlled context.

Any ideas how it could be achieved?

An example is something like this:

class Foo {
    constructor(name) {
        this.name = name;
    }

    sayMyName() {
        console.log(this.name);
        return this.name;
    }
}

class Scope {
    constructor(reqId) {
        this.foo = new Foo('Hi!');
        this.reqId = reqId;
    }

    do(callback) {
        const func = callback.bind(this, this);
        func();
    }
}

class Controller {
    constructor() {
        this.foo = new Foo('Hello!');
    }

    unscoped(req, res, next) {
        var a = 1;
        res.json({
            success: this.foo.sayMyName()
        });
    }

    scoped(req, res, next) {
        req.scope.do((ctx) => {
            var a = 1;
            res.json({
                success: this.foo.sayMyName()
            });
        });
    }
}

I want this.foo.sayMyName() to return 'hi' in Controller.scoped and 'hello' in Controller.unscoped

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Victor Ferreira
  • 6,151
  • 13
  • 64
  • 120
  • You can change the context of a function using `yourFunction.bind(context)` (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind) or With `.call(context)` (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call) or `.apply(context)` (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) – Seblor May 29 '18 at 14:10
  • 1
    Could you give an example about what you want to achieve – obey May 29 '18 at 14:10
  • 2
    "*a module that receives a function and then changes its context.*" - there is [the native `bind` method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind) already?! But no, when one uses an arrow function that means that you don't *want* the context to be changed, and you shouldn't try to do. It's just like the user passed a function that doesn't use the `this` keyword at all - they don't need a dynamic context. – Bergi May 29 '18 at 14:13
  • 1
    If someone chooses to pass you an arrow function or an already-bound function, they are basically choosing to skip whatever logic you've added. Working around that would be breaking the semantics of the language. Don't do that. – loganfsmyth May 29 '18 at 15:52

1 Answers1

2

Neither Function.prototype.bind nor Function.prototype.call nor Function.prototype.apply can be used on arrow functions to change their context.

var arrowFunc = () => {console.log(this === myObject);};

var functionExpression = function() { console.log(this === myObject); };

var myObject = { id : "sampleObject"};

var boundFunctionExpression = functionExpression.bind(myObject);
console.log("Function expression bound with Function.prototype.bind :");
boundFunctionExpression();

var boundArrowFunc = arrowFunc.bind(myObject);
console.log("Arrow function bound with Function.prototype.bind :");
boundArrowFunc();

console.log("Arrow function called with Function.prototype.call :");
arrowFunc.call(myObject);
console.log("Arrow function called with Function.prototype.apply :");
arrowFunc.apply(myObject, []);

So no, I don't think you can achieve this.

More on the differences between arrow function and function expressions / declarations.

Guillaume Georges
  • 3,878
  • 3
  • 14
  • 32