2

Learning how to write JS Fn that accepts an unknown number of arguments.

function foo(a,b,c,d){
    //do something
    //return something
}

var bar = function () {
    var arg = Array.from(arguments);
    var lastIndx = arg.length;
    var parArray = arg.slice(1,lastIndx);
    var argMnts = arguments[0];
    return arguments[0].apply(this, parArray);
};

calling bar thus works:

bar(foo,1,4,3,7);

calling it like so:

var tester = bar(foo,1,4,3,7);
tester();

results in: tester is not a function

From my research I suspected it might have to do with the scope of "this" or arguments so I assigned their values to variables, subbed the vars, and the result was the same.

Some insight would be immensely appreciated.

1 Answers1

2

In your example, calling bar() returns whatever the results of calling foo(...) is. So, if you want to be able to do this:

var tester = bar(foo,1,4,3,7);
tester();

Then, foo(...) has to return another function that can get assigned to tester and can then get called again.


If, instead of the way it is above, if you don't want bar(foo, ...) to actually call foo(), but want it to return a function that will then call foo() with the appropriate arguments, you can change bar() to this:

var bar = function () {
    var args = Array.from(arguments);
    var fn = args.shift();
    var self = this;
    return function() {
        return fn.apply(self, args);
    }
};

var tester = bar(foo,1,4,3,7);
tester();

Here, bar() returns a function, that (when called) will call foo().


Or, with the right ES6 support, you could use rest parameters;

var bar = function (fn, ...args) {
    var self = this;
    return function() {
        return fn.apply(self, args);
    }
};

or, you could use .bind() with rest parameters and the spread operator:

var bar = function (fn, ...args) {
    return fn.bind(this, ...args);
};
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • `Array.from` is from ES6, so I think it's safe to assume they are using it. – 4castle Aug 07 '16 at 16:16
  • @4castle - ES6 support does not always come in a giant monolith where you have it all or don't have any of it. For example, node 4.x has `Array.from()`, but not rest or spread. node 5.x has `Array.from()` and spread, but not rest. node 6.x has all three. Anyway, my answer now offers several choices. – jfriend00 Aug 07 '16 at 16:22
  • I learned alot from this thank you! regarding your answer: return fn.apply(self, args); wouldn't fn need to refer to the first index of the args [] and args be replaced with an [] containing all indices but the first? – InaMastabba Aug 07 '16 at 16:38
  • @InaMastabba - That's what `args.shift()` does. `args.shift()` grabs the first item from the `args` array and the others are moved down in the array. So, you then have `fn` as the first argument and `args` as the rest of the arguments. – jfriend00 Aug 07 '16 at 17:07