2
let dragons = [
    { name: "Test1", power: "Fire" },
    { name: "Test2", power: "Lightning" },
    { name: "Test3", power: "Fire" },
    { name: "Test4", power: "Fire" },
    { name: "Test5", power: "Speed" },
    { name: "Test6", power: "Fly" }
];

let hasPower = power =>
    obj => 
        obj.power === power

let fireDragons = dragons.filter(hasPower("Fire"));

I get the currying part, but what I don't get is how the currying function gets passed obj from filter, can someone explain that to me?

  • If I told you calling filter this way is equivalent to: `hasPower("Fire")(dragons[index])` for each dragon, would that help? – Randy Casburn May 12 '18 at 18:53
  • 1
    [Array.prototype.filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) will pass each item of the dragons array to the function you pass it. More on filter [here](https://stackoverflow.com/a/50075368/1641941) – HMR May 12 '18 at 18:54
  • I get that's how currying works, but what I don't understand is how the dragon object is getting passed to hasPower –  May 12 '18 at 18:54
  • That's the magic HMR just commented on...it is a callback feature of `filter()` – Randy Casburn May 12 '18 at 18:55
  • To be correct; each dragon is passed to hasPower("Fire") – HMR May 12 '18 at 18:55
  • It would help if you used regular functions instead of arrow functions. Try it! – ibrahim mahrir May 12 '18 at 18:56
  • Right, misworded I'm going to read that doc you just sent, if you would like you can post that with your answer –  May 12 '18 at 18:57
  • 1
    Each dragon object is passed to the return value of `hasPower` which is also a function. – ibrahim mahrir May 12 '18 at 18:57
  • Because your `hasPower` function returns a callback function for filter where `obj` param will be each object from dragons array inside filter. – Nenad Vracar May 12 '18 at 18:58
  • To really understand how Array#filter iterates through the array to send the each element value to the filter callback, you may need to study its Polyfill provided here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter – Rem Lampa May 12 '18 at 19:01

1 Answers1

3

Before understanding the code you shared, let's first learn the syntax of the filter function.

var newArray = arr.filter(callback(currentValue[, index[, array]])[, thisArg])

callback Function is a predicate, to test each element of the array. Return true to keep the element, false otherwise, taking three arguments: element, index and the array itself. thisArg is optional, though.

Now, let's try to understand the code.

let hasPower = power =>
    obj => 
        obj.power === power

The function hasPower can be updated as:

let hasPower = function (power) {
    return function (obj) {
        return obj.power === power;
    }
}

Just keep in mind, whenever hasPower would be executed, it will simply return a function (which would be executed later) and will have access to the power variable. (Read more: Closure)

and now the fireDragons,

let fireDragons = dragons.filter(hasPower("Fire"));

You are passing a function as a parameter to the filter function (invoking it as well).

When this line of code is executed, the function hasPower("Fire") would be executed first and whatever is returned from that function would be passed to the filter as the callback function.

Basically, it would become something like:

let fireDragons = dragons.filter(function (obj) {
    // Having access to the `hasPower` variable which is "Fire" in your case.
    return obj.power === power;
});

or exactly like this: enter image description here

Always try to debug in the developer tools to understand how the code works and feel free to replace the arrow functions with regular ones to make it more readable/understandable.

Rahul Gandhi
  • 1,035
  • 1
  • 11
  • 24