简体   繁体   中英

A javascript function that receives and returns functions

I have a JavaScript function:

function oneOf() {
    return arguments[Math.floor(Math.random()*arguments.length)];
}

It is designed to take in variable number of arguments and spit out a random one, and this works. I can't get it to take a list of object methods and execute one. How would I do this?

Insight #1

Function.prototype.apply allows you to "splat" an array into the arguments list:

function sayAll() {
  console.log(arguments);
}

sayAll(1, 2, 3, 4);
// [1, 2, 3, 4]

sayAll.apply(null, ["a", "b", "c"])
// ["a", "b", "c"]

Insight #2

Functions can be invoked with parenthesis (see above).

Combining these two insights, we get the following:

function oneOf() {
  var f = arguments[Math.floor(Math.random()*arguments.length)];
  return f();   // Via insight #2
}

// Via insight #1
oneOf.apply(null, [someFunction, anotherFunction]);

If these functions are "methods" on an object and need to retain their this context, then we'll need a third insight.

Insight #3

Function.prototype.bind allows creating a function with a fixed this context:

function sayWhatThisIs() {
  console.log("This is", this);
}

var coolObject = {
  cool: true,
  sayWhat: sayWhatThisIs
};

coolObject.sayWhat();
// This is {cool: true, ...}

oneOf.apply(null, [coolObject.sayWhat.bind(coolObject),
                   sayWhatThisIs.bind(coolObject)]);
// Two variations of binding `sayWhatThisIs` to `coolObject`

Insight #3a

We could also pass on the this context of oneOf to Function.prototype.apply :

function oneOf() {
  var f = arguments[Math.floor(Math.random()*arguments.length)];
  return f.apply(this);
}

onOf.apply(coolObject, [coolObject.sayWhat, sayWhatThisIs]);
// Now applying insight #3a to set `onOf`'s `this` context to `coolObject`.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM