2

I have this code:

function Selector(){
    this.name = 'Selector';
    this.select = function(fName){
        return this[fName]
    }

    this.funcOne = function(arg){
        console.log(arg + this.name)
    }

}
var mySelector = new Selector();
mySelector.select('funcOne')('Hello');

When I call funcOne with this implementation, the context within funcOne is the function itself, not the Selector instance. How can I maintain the context of the instance by calling funcOne in this way?

Edit: I'm using Extendscript, which is an ES3 environment, so I can't use bind() or arrow functions. What I need exactly is to be able to pass the parameters of the selected function separately, since the idea is, on one hand, to be able to select different functions with a number of different arguments, and on the other, to be able to chain calls using parentheses syntax:

function Selector(){
    this.name = 'Selector';
    this.select = function(fName){
        return this[fName]
    }

    this.funcOne = function(arg){
        console.log(arg + this.name)
        return this.select
    }

    this.funcTwo = function(arg1, arg2)
    {
        console.log(arg1 + arg2 + this.name)
        return this.select
    }
}
var mySelector = new Selector();
mySelector.select('funcOne')('Hello');
mySelector.select('funcTwo')('Hello ', 'my ')('funcOne')('Hello again ');

So using a pointer to the instance does not help either, since the problem with the context still remains:

function Selector(){
    var self = this
    this.name = 'Selector';
    this.select = function(fName){
        return this[fName]
    }

    this.funcOne = function(arg){
        var s = self; // undefined
    }
}
Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Miguel
  • 709
  • 7
  • 21
  • You can either bind the function to the context of `Selector` using `.bind(this)` (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind) or you can declare `Selector.prototype.funcOne` outside of the function constructor. – jamis0n May 20 '19 at 21:15
  • I'm using Extendscript, wich is an ES3 enviroment, so I can't use bind() or arrow functions – Miguel May 20 '19 at 21:20
  • Functions are, generally speaking, scoped according to the object on which they’re called. So here, `mySelector.select` gets `mySelector` as its scope, but the result of that call, the function it returns, is detached from the object when it’s invoked, so it doesn’t get the `mySelector` scope. You can be explicit about the desired scope via `bind`, arrow functions (auto-binding), or by using `function.apply` or `function.call`. – ray May 20 '19 at 21:22
  • The olde `self` trick worked since ES1: `var self = this; return function(arg) { self[fName](arg); }`. – Bergi May 20 '19 at 21:30
  • `return this[fName].bind(this);` – vbuzze May 20 '19 at 21:39
  • I don't think this is a duplicate question, I readed that post before but it don't aswer my question. As I've mentioned, I can't use `bind()` or arrow functions. What I wan't exactly I to call the function using double parenthesis, not passing the arguments on the select `method` so `var self = this; return function(arg) { self[fName](arg); }` don't solve my question, at least in the way that is proposed – Miguel May 20 '19 at 21:53
  • alternative to bind for ES3: `function bindFunc( thisValue, func) { return function() { func.apply( thisValue, arguments) }; }` – traktor May 21 '19 at 02:44
  • But `var self = this; this.select = function ( fName) { return self[ fName]; }` and using `self` instead of `this` in all the methods was a lot easier to get working ;-) – traktor May 21 '19 at 03:17

0 Answers0