0

I have a functionA which accepts a function as a parameter. I want to manipulate the arguments of that function in functionA and return this as functionC. I found that I can do this with .apply(), however the original context of functionB is lost and instead replaced by functionA.

For example,

var factory = {
   return {
       fnB: function() {}  
   }
};

fnA(fn) {
    return fnC(params) {
        var customparams = [params, {something: else}]
        return method.apply(null, customparams);
     }
}

var load = fnA(factory.fnB);
load(params);

However when I execute load(params), I lose functionB's context. FunctionB is defined as a method from a factory. How can I go about this? Thanks!

irisgve
  • 119
  • 1
  • 10
  • 2
    Where's `functionB`? What's `method`? Why isn't the code using `fn`? Are you aware that `customparams` is falling prey to [*The Horror of Implicit Globals*](http://blog.niftysnippets.org/2008/03/horror-of-implicit-globals.html)? – T.J. Crowder May 14 '15 at 07:37
  • 2
    "*FunctionB is defined as a method from a factory.*" - then you'll have to `bind` it: `load = functionA(factory.functionB.bind(factory))`. Alternatively, give `functionA` a second argument for the context, or use `this` instead of `null` in `functionC` and call `load` on the factory from that you got `functionB` from. – Bergi May 14 '15 at 07:44

1 Answers1

2

I'm going to assume method is actually fn, and that functionB is a function assigned to an object property, and that the various syntax errors aren't present in your actual code:

var obj = {
    name: "foo",
    functionB: function() {
        console.log(this.name); // <== Using `this` to refer to `obj`
    }
};

function functionA(fn) {
    return function functionC(params) {
        var customparams = [params, {something: "else"}];
        return fn.apply(null, customparams);
    };
}

var load = functionA(obj.functionB);
load("a", "b"); // Fails because `this` in the call to `functionB` isn't `obj`

If so, you can fix it in a couple of wasy:

1) By using Function#bind whne passing functionB into functionA:

var load = functionA(obj.functionB.bind(obj));
load("a", "b"); // Works

var obj = {
  name: "foo",
  functionB: function() {
    snippet.log(this.name); // <== Using `this` to refer to `obj`
  }
};

function functionA(fn) {
  return function functionC(params) {
    var customparams = [params, {
      something: "else"
    }];
    return fn.apply(null, customparams);
  };
}

var load = functionA(obj.functionB.bind(obj));
load("a", "b"); // Works
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

2) By adding a second argument to functionA, as Bergi suggested, that it uses when calling fn (see in the snippet) — this approach is used by many of the ES5 Array methods, for instance:

var obj = {
  name: "foo",
  functionB: function() {
    snippet.log(this.name);
  }
};

function functionA(fn, thisArg) {           // <=== Accepting thisArg
  return function functionC(params) {
    var customparams = [params, {
      something: "else"
    }];
    return fn.apply(thisArg, customparams); // <=== Using it
  };
}

var load = functionA(obj.functionB, obj);   // <=== Passing it
load("a", "b"); // Works
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • This solved it, thanks! I thought of using bind in the obj itself but not that scalable so this is a good way of doing it. Thanks a lot! – irisgve May 14 '15 at 07:49