2

Can someone please explain why we can simply pass a method name to a higher order function and everything works just fine. I know in something like Java I have to call the method words on each element individually. I was told that in Javascript if method signature matches we can simply pass in the name of the function with () and it will work. It is great but I want to know whats going on in the background. Why are we able to do this in javascript ?

function words(str) {
  return str.split(" ");
}


var sentences = function(newArr){
    return newArr.map(words);
}
Yasin Yaqoobi
  • 1,568
  • 2
  • 22
  • 34
  • 2
    functions are objects in javascript. – Daniel A. White Oct 15 '16 at 01:28
  • I think the better question is why not? You did not mention any suspected theoretical issue why this shouldn't work, so why not allow it in a language? – ASDFGerte Oct 15 '16 at 01:28
  • It's just a reference, it would be the same as `arr.map(function() {})` where the callback is called for each value in the array – adeneo Oct 15 '16 at 01:29
  • @RobG I know how map works. I am probably not explaining this correctly but I am just curios as to how this works. You look at some JS-FP code and it is hard to understand how they can take shortcuts like this. I want to understand the basis so I can use this feature of javascript correctly/efficiently. – Yasin Yaqoobi Oct 15 '16 at 01:31
  • @DanielA.White I understand functions are objects in JS. But it is just a word that everyone throws around. Not sure how that makes any difference. – Yasin Yaqoobi Oct 15 '16 at 01:32

3 Answers3

1

You are calling the words function repeatedly. You're calling it for each iteration of the map function.

The map function takes a callback which it runs for every iteration. That callback is usually in the form of

function (elementOfNewArr, indexOfNewArr, newArr) { }

Because functions are objects, you can store them on a variable and use that new variable name to call that function, instead of its original one. That's mostly the use of functions as objects. You can toss them around.

let foo = function () { return 'jasper!'; } 
let boo = foo;
let ron = boo;   // ron() will now return 'jasper!'

So, what you've done is plop in your callback function, though it was defined elsewhere. Since callback functions, like all functions are objects, you can declare that callback function, "saving" it to whatever variable you want and use it in anywhere that you can use it normally.

This is super useful if you have to use the same function in more than one place.

Gabriel Kunkel
  • 2,211
  • 3
  • 20
  • 35
1

In many languages you can pass a reference to a function as an argument to a function. That then allows the host function to use that argument and call that function when appropriate. That's all that is going on in Javascript. When you pass the name of a function without the () after it, you're just passing a reference to the function. That enables the host function to use that function as an argument and call it some time later.

In your specific example, .map() expects you to pass in a function that it will call once for each item in an array. So, you pass the name of a function that will then get called multiple times, once for each item in the array. That function you pass has a bit of a contract that it has to meet. It will be passed three arguments (value, index, array) and it must return a value that will be used to construct a new array.

In Javascript, since there is no argument type checking by the language, it is the developer's responsibility to make sure the arguments of the function you are passing match what the caller of that function will actually pass to it and you have to consult documentation of the calling code itself to know what arguments will be passed to it. You can name the arguments anything you want (that is entirely internal to your function implementation), but the order and the quantity of the arguments is determined by the caller and you must declare your function to match what the caller will provide.

Once thing that confused many in Javascript.

If you pass just a function name, you are passing a reference to the function (something that the host function can call at some later time).

array.map(myFn)        // passes a function reference

Or, use an inline function (same outcome):

array.map(function(value, index, arr) {
    // code goes here
})

If you put parens at the end of the function name, then the function is executed immediately and the return value of that function execution is what is passed:

array.push(myFn());    // pushes the result of calling myFn()
jfriend00
  • 580,699
  • 78
  • 809
  • 825
0

What I believe you are misunderstanding is that functions themselves can be treated the same as other variables in javascript. Consider this example:

var newArr = [1,2,3,4];
newArr.map(function(item){
    return item * item;
});

In the above example, a function is passed as an argument to the map() function. Notice that it is described anonymously (no function name given). You can accomplish the exact same thing like this:

var newArr = [1,2,3,4];
function squared(item){
    return item * item;
}

newArr.map(squared);

These two examples achieve the same thing, except in the second example, rather than writing the function in place, we define it earlier in the code. If it helps, you can even create the function in the same way as you would any other regular variable:

var squared = function(item){
    return item * item;
};

You can pass this function around the same way. If you want to know the difference between defining functions in these ways try var functionName = function() {} vs function functionName() {}

Community
  • 1
  • 1
Matt Way
  • 28,863
  • 10
  • 70
  • 79