JavaScript has what are called "first-class functions", meaning that a function can be itself an argument or return value in a different function. This allows you to utilize a programming style known as "functional programming".
Here is an example. Let's say we have an array of note names, and we want to
convert that to an array of MIDI numbers. Assuming we have a
noteNameToMIDINumber()
function, we can do something like this:
let noteNames = ["C4", "C#4", "D4", "G3"];
let midiNumbers = noteNames.map(noteNameToMIDINumber); // [60, 61, 62, 55]
The
map
method takes in a function as an argument, without the open-and-close parens
you usually place after functions. This means the function has not yet been
called. Instead, map
calls the function—in this case
noteNameToMIDINumber
—once for each element in noteNames
, building a new
array with the result.
You can think of the above code as equivalent to the following:
let noteNames = ["C4", "C#4", "D4", "G3"];
let midiNumbers = [];
for (let i = 0; i < noteNames.length; i += 1) {
let midiNumber = noteNameToMIDINumber(noteNames[i]);
midiNumbers.push(midiNumber);
}
You can see how map
greatly simplifies the logic and control flow. You
should also look up other functional array methods, such as
filter
and
reduce
.
Whenever we use a function as an argument, we can say that function is a
"callback function". Callback functions may be either "synchronous" or
"asynchronous". The example with .map()
above is an example of a synchronous
callback, because it runs the moment you call .map()
. Contrariwise,
asynchronous functions will wait for a certain event to occur before
executing. This functionality is incredibly useful in musical applications,
since we frequently find ourselves waiting for a cue before beginning an
action.
$("#my-button").on("click", () => {
// do something here
});
Here is an example of an asynchronous callback function using jQuery. Here, we are waiting for the user to click on an HTML element with the ID "my-button" before launching our code. Also note that the function in this example does not have a name. This is an example of an "anonymous function", or what some languages call a "lambda". I know this may seem like a lot of vocabulary—asynchronous callbacks with anonymous functions—but this programming paradigm is actually quite common in JavaScript, and you should get comfortable with the concepts and the terminology.
map
, filter
, and reduce