How to interpret MDL syntax

let newArray = arr.filter(callback(element[, index, [array]])[, thisArg])

above is a syntax explanation from MDL document for array.filter
But I cannot quite grasp things like ( and[, thisArg].
Can someone break it down and clarify for me?
Below is the URL for the MDL document.

Hi there.

So, the .filter() method of the Array object is used to return a new array containing only the elements of the original array which meet the criteria of the callback function.

Let’s break down the example you’ve posted:
let newArray = arr.filter(callback(element[, index, [array]])[, thisArg])

Hopefully, you’re fine understanding what we’re doing with this:
let newArray = arr.filter()
and it’s just the bit inside the method parentheses which are confusing you?

So, let’s look at what we’ve got inside the parentheses.

callback(element[, index, [array]])[, thisArg]

The items which are in square brackets [ ] are optional parameters. This is a fairly common notation you’ll encounter a lot in documentation.

Since these parameters are optional, you can use them if you want or you can ignore them. :slight_smile:

So, the bare minimum we need to provide to use .filter() is:

arr.filter(callback(element))

However, whilst element is not an optional parameter it’s also not a parameter that you provide directly. JavaScript automatically provides this parameter to your callback function when it processes the .filter() operation.

Let’s look at the individual components of the original expression:

callback(element[, index, [array]])[, thisArg]

callback()

The value of the callback parameter is what’s called a predicate function. This is, simply put, a JavaScript function which returns a boolean value: either it’s true, or it’s false.

You can use a previously defined function, or you can provide the parameter in the form of an anonymous function.

callback() takes three parameters:

element

The element parameter might be a bit strange to you, because you don’t provide the value for this parameter. JavaScript automatically provides the value for element to your callback function as it iterates over the array during the .filter() method call.

index (optional)

Your predicate function can, if you wish, get the index of the current item of the array being evaluated. Again, like the element parameter, this is automatically provided by JavaScript and is not something you need to pass directly.

array (optional)

This is another automatically provided parameter, containing the array which you are filtering.

The .filter() method has a second parameter, other than callback:

thisArg (optional)

thisArg tells JavaScript what you want to refer to when you’re using the reserved keyword this. I don’t think you’d need this parameter at all for the exercises here on Codecademy…

Let’s write a small example program to demonstrate how this works, shall we?

// let's initialise an array
const someFruit = ["apple","orange","pear","banana","watermelon","kiwi fruit","strawberry","guava","mango"];

// now, let's define our predicate function ahead of time.
function bigFruit(fruit) {
    // return fruit longer than 5 characters!
    return fruit.length > 5;
}

// let's filter our fruit so we only get the "big fruit"
// bigFruit is being passed as the value for the callback parameter
const filteredFruit = someFruit.filter(bigFruit);

// let's see what we got!
console.log(filteredFruit); // output: [ 'orange', 'banana', 'watermelon', 'kiwi fruit', 'strawberry' ]

As you can see, we had an array and used the filter() method to find fruit whose names were longer than 5 characters.

Let’s write another one, this time demonstrating the optional parameters of index and array.

// let's initialise an array
const someFruit = ["apple","orange","pear","banana","watermelon","kiwi fruit","strawberry","guava","mango"];

// now, let's define our predicate function ahead of time.
function bigFruit(fruit, index, array) {
    // some basic examples for the optional parameters:
    console.log(`.filter() is evaluating ${fruit}, which is at index ${index} of the array.`);
    console.log(`The array is: ${array}\n`);
    // return fruit longer than 5 characters!
    return fruit.length > 5;
}

// let's filter our fruit so we only get the "big fruit"
const filteredFruit = someFruit.filter(bigFruit);

// let's see what we got!
console.log(filteredFruit);

Notice that I have adjusted my bigFruit() function, so it now expects three parameters:

  1. fruit, which is the element parameter from the MDN docs,
  2. index, which is the index parameter from the MDN docs,
  3. and array, which is the array parameter from the MDN docs.

Running this program, we see the following on the console:

.filter() is evaluating apple, which is at index 0 of the array.
The array is: apple,orange,pear,banana,watermelon,kiwi fruit,strawberry,guava,mango

.filter() is evaluating orange, which is at index 1 of the array.
The array is: apple,orange,pear,banana,watermelon,kiwi fruit,strawberry,guava,mango

.filter() is evaluating pear, which is at index 2 of the array.
The array is: apple,orange,pear,banana,watermelon,kiwi fruit,strawberry,guava,mango

.filter() is evaluating banana, which is at index 3 of the array.
The array is: apple,orange,pear,banana,watermelon,kiwi fruit,strawberry,guava,mango

.filter() is evaluating watermelon, which is at index 4 of the array.
The array is: apple,orange,pear,banana,watermelon,kiwi fruit,strawberry,guava,mango

.filter() is evaluating kiwi fruit, which is at index 5 of the array.
The array is: apple,orange,pear,banana,watermelon,kiwi fruit,strawberry,guava,mango

.filter() is evaluating strawberry, which is at index 6 of the array.
The array is: apple,orange,pear,banana,watermelon,kiwi fruit,strawberry,guava,mango

.filter() is evaluating guava, which is at index 7 of the array.
The array is: apple,orange,pear,banana,watermelon,kiwi fruit,strawberry,guava,mango

.filter() is evaluating mango, which is at index 8 of the array.
The array is: apple,orange,pear,banana,watermelon,kiwi fruit,strawberry,guava,mango

[ 'orange', 'banana', 'watermelon', 'kiwi fruit', 'strawberry' ]

As you can see, as .filter() iterates over our array to find the fruit whose names are over 5 characters, I’m able to use the index and array parameters inside the callback function.

In this case, all I’ve done is output them to the console. I’ll leave it to you to come up with more interesting uses, as you carry on learning. :slight_smile:

Hopefully that’s made things a bit clearer? If not, and you’re still confused, let us know. :slight_smile:

2 Likes

Hey , I am working on the .filter() method myself and that was a great response !

I am still having some troubles though on understanding how to filter strings from the array . How do I define the criteria to filter out 1 or 2 strings from the array ? For example , I need to filter out 3 strings from the original array which tells a story.

Since .filter() is a boolean function I want it to return the original array with all the strings which are TRUE , and exclude the FALSE ( the ones I define as false ). I tried this doing the following :

Looks to me like you have an error in your callback function:

const betterWords = storyWords.filter((word) => { if word != 'extremely'|| 'literally'|| 'actually'}{
  return word
});

Hey pitcycoder!

Yes , I have fixed that , but still all I can log is an empty array.

Const betterWords = storyWords.filter((word) => { word = “literally” || “actually” || “extremely”

});

console.log(betterWords)

Which way should I define the function ir order to filter out the false strings ?

Edit :

Found out what the problem was , I had to :

const betterWords = storyWords.filter((word) => word !== ‘literally’ || word !== ‘actually’ || word !== ‘extremely’);

1 Like

Kudos on solving it yourself :+1:, however there’s a more elegant way to do it which doesn’t involve hard-coding the “unnecessary” words into the callback function:

const betterWords = storyWords.filter(word => {
  return !unnecessaryWords.includes(word);
})
1 Like