Ian Hill
Ian Hill

Reputation: 399

Accessing parent function when using Function.prototype methods

I'm playing around with Function.prototype as a learning exercise and was trying to make a generic curry method that could be used like this:

// Any old function
var myFn = function(arg1, arg2) {
    console.log(arg1, arg2);
};

// Curry some parameters and return a new function
var myFnCurry = myFn.curry("A");

// Call the curried function, passing in the remaining parameters
myFnCurry("B"); // Outputs: A B

It's fairly straight forward to implement this feature as a function rather than a method using the following approach:

var curry = function(fn) {
    var slice = Array.prototype.slice,
        args = slice.call(arguments, 1);
    return function() {
        fn.apply(this, args.concat(slice.call(arguments)));
    };
};

// Example
var myFnCurry = curry(myFn, "A");
myFnCurry("B"); // Outputs: A B

However, I really wanted to be able to utilise the Function prototype, like this:

Function.prototype.curry = function() {
    var slice = Array.prototype.slice,
        args = slice.call(arguments);
    return function() {
        // If we call curry like this: myFn.curry()
        // how can we get a reference myFn here?
        ???.apply(this, args.concat(slice.call(arguments)));
    };
};

I'm not sure how to get a reference to the myFn function (denoted by the ??? above) that the curry method is being called from.

Is there a way to access the parent function in this circumstance?

Cheers,

Ian

Upvotes: 2

Views: 567

Answers (1)

Alexey Lebedev
Alexey Lebedev

Reputation: 12197

You're calling curry in a context of your function object (myFn.curry), and therefore inside of curry this refers to that function. But your inner function will be called in the context of global object, that's why you need to store the reference to the outer function in a closure.

Function.prototype.curry = function() {
  var self = this, args = [].slice.call(arguments)
  return function() {
    return self.apply(this, args.concat([].slice.call(arguments)));
  }
}

Upvotes: 2

Related Questions