Can anybody explain the flow of the code? I need to know how the function 'isEven' gets the 'x' value
$(document).ready(function(){
var array = [1,2,3,4,5];
function isEven(x){ //checks if a value is even
console.log(x)
return x % 2 == 0;
}
var newArray = array.filter(isEven); //uses a callback to check if an element is even
console.log(newArray);
});
As stated in the comment in your code, you are passing a callback, so here the current item processed in .filter() will be automatically passed to this callback function, or in other words isEven function will be called with the current item from .find() call.
As you can see in the MDN Reference for .find():
callback
Function to execute on each value in the array, taking three
arguments:
element The current element being processed in the array.
So writing:
array.filter(isEven);
Is equivalent to writing:
array.filter(function(item){
isEven(item);
});
The solution is in this line
var newArray = array.filter(isEven); //uses a callback to check if an element is even
Here you are calling the method "filter" on the array. Filter takes a method that returns true or false, and calls it on each of the array element, passing the element itself. That line could be implemented like this
let newArray;
for(let x: array){
if(isEven(x)){
newArray.push(x);
}
}
The filter() function on an array takes a function as it's input. In this case that input function is the isEven function. The filter function then iterates over the array and runs the isEven function over each of the elements. It then filters out any elements in the array for which the function returned false.
Note that in the parentheses of the filter function you do not specify any arguments to the isEven function. That is because filter does this for you.
Your code is equivalent to:
var newArray = [1, 2, 3, 4, 5].filter(x => x % 2 == 0);
The x value is taken in your first array. See the doc.
filter is a function defined in the Array API, it receives as a parameter a "this" which in your case is the variable "array" and a callback that would be "isEven", inside that "this" is the values of your array, it just need to go through it and call each one to your function.
Read this
array.filter will automatically take this as its argument if not passed, when it is getting looped. Check here for more details.
So, in case of your array this values corresponds to the elements 1,2,3,4,5
If a thisArg parameter is provided to filter, it will be used as the
callback's this value. Otherwise, the value undefined will be used as
its this value. The this value ultimately observable by callback is
determined according to the usual rules for determining the this seen
by a function.
Related
Here is piece of code I am trying to fully understand:
const words = ['chair', 'music', 'pillow', 'brick', 'pen', 'door'];
const shortWords = words.filter(word => {
return word.length < 6;
});
My current assumption is that shortWords is a function that is having another function passed in as a parameter.
So shortWords is to use .filter on the words array. The argument (which is also a function?) thats passed into the shortWords function is supposed to return all words with a length less than 6 letters from the array.
Is my understaning correct or am I missing something?
Yes, you are correct except the fact that shortWords is a variable that stores an array returned by .filter function.
The types of words is an array.
const words = ['chair', 'music', 'pillow', 'brick', 'pen', 'door'];
Array.filter is a method/function that allows you to loop through the array. As the name suggests, it is used to filter the array and create a new array.
Array.filter accepts a function as a parameter. In your provided snippet you have passed an arrow function as a parameter inside the filter method.
This is similar to the following code with simple function:
function filterFunctionAsParam(word) {
return word.length < 6;
}
const shortWords = words.filter(filterFunctionAsParam);
The filter method does not change the array it acts upon. That is it does not mutate words array. The value of words array does not change. Rather it returns a filtered array. shortWords is that filtered array.
For each array element, if the condition returned by the filterFunctionAsParam is true, the element is returned by the filter function.
This can also be achieved with Array.map, Array.reduce methods.
My current assumption is that shortWords is a function that is having another function passed in as a parameter.
No, filter is a function which has another function passed to it as a parameter.
It operates on an array, and calls the passed-in function on each element in the array - if it returns true then that array item is included in the result of calling filter.
I would like to understand why my console.log outputs the elements which have been placed before some().
function isBiggerThan10(element, index, array) {
console.log(element);
return element > 10;
}
[2, 5, 8, 1, 4].some(isBiggerThan10);
From my understanding, the elements should be outputted if they are given as parameters of isBiggerThan10(). I guess this is because of the array function some(). If so, how can I write a similar code like what some() does? The goal is to output all elements of the array in the function myElements(). myElements should be a parameter of the function test().
This is what I have tried:
Array.prototype.test = function(i) {
console.log(i);
};
function myElements(element) {
console.log(element);
}
[2, 5, 8, 1, 4].test(myElements);
But it seems like that I don't understand the logic behind of it.
some() method is used to check a condition on all array elements (or specified elements) and returns true if any of the array elements matches the condition and returns false if all array elements do not match the condition.
In case why all the element is being printed?, It is the fact that when you call the function you have console logged it, that's it .
so if you want to output all the numbers greater than 10 you can use the filter method.
function isBiggerThan10(element, index, array) {
return element > 10;
}
console.log([2, 5, 8, 1, 4].filter(isBiggerThan10))
The syntax of Array.prototype.some() function specifies that you call some() over an array, and it takes for parameters a callback function (function isBiggerThan10() in your snippet), which itself takes one argument and 3 other optional ones. The main argument required is element which, is the value of each element that you iterate over from the array that calls some(). You can check the docs here.
Syntax
arr.some(callback(element[, index[, array]])[, thisArg])
Parameters
callback: A function to test for each element, taking three arguments:
element: The current element being processed in the array.
TLDR: some() iterates through each element of the array until condition is met, and the element argument in the callback function holds the value of the current element that is being iterated.
some function calls your isBiggerThan10 function for every element of the array. That's why all array elements are printed to console. Please refer https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some for more details
This question already has answers here:
Understanding Javascript callback parameters
(3 answers)
Closed 5 years ago.
var animals = ["cat","dog","fish"];
var lengths = animals.map(function(c) {
return c.length;
});
console.log(lengths);//[3, 3, 4]
Here is the code. I don't understand where this 'c' argument comes from.
I tried to change this argument to another one (any word, actually, in both places), and the console.log result is always the same!
But this 'c' is not defined anywhere! Where does 'the engine' get the value of this 'c'?
You've asked two slightly different questions. First to the question body:
I don't understand where this 'c' argument comes from. I tried to change this argument to another (any word, actually, in both places), and the console.log result is always the same!
But this 'c' is not defined anywhere!
Where does 'the engine' gets the value of this 'c'?
You define the parameter name (as you've noticed, you can choose any name for it you like). The value comes from the array, because map calls your callback and determines what argument to pass for that parameter.
Here's a conceptual implementaton of Array.prototype.map, which make make this clearer:
// CONCEPTUAL ONLY, NOT AN ACTUAL VERSION OF IT
function maplike(array, callback) {
var result = [];
for (var i = 0; i < array.length; ++i) {
result[i] = callback(array[i]);
// ^^^^^^^^--- where 'c' comes from
}
return result;
}
var animals = ["cat","dog","fish"];
var lengths = maplike(animals, function(c) {
return c.length;
});
console.log(lengths);//[3, 3, 4]
Do array elements have names by default in JavaScript?
Sort of, but not in the way you're thinking. The name of the element is its index, 0, 1, etc. In fact, JavaScript arrays aren't really arrays at all* and those indexes are converted to string property names (in theory; in practice, JavaScript engines optimize it).
* (disclosure: that's a post on my anemic little blog)
You're telling the interpreter how the parameter is called, here:
function(c) {
^
Array.prototype.map() requires a callback that accepts up to 3 parameters. The first parameter is always the "current item", which you happen to have named c.
For a more in-depth explanation, have a look at T.J. Crowders answer, as well.
In javascript, functions are first class object, which means they can be assigned to variables, passed as function parameters and returned from values. The Array.prototype.map function takes a function with it's first parameter denoting an item of the array. When invoked, the map function executes the given function for each of the items and creates a new array from the outputs of the given function.
In your case, you are defining the input function on the fly, inside the map function.
You can actually define the function outside and pass the function by reference inside map like below.
function getLength(item) {
return item.length;
}
var animals = ["cat","dog","fish"];
var lengths = animals.map(getLength);
console.log(lengths);//[3, 3, 4]
Here, you can see it outputs the same result.
The code does not know what is the parameter named. You map an array. map function creates a new array in the lengths variable (variable being assigned to). How? It provides to the function parameter inside it, each element in the current array one-by-one by value.
Here the value is actual string name ("cat" or "dog" or "fish").
In javascript, parameters can be optional. This map function can take three parameters, currentValue, index, array. In your case, c provides currentvalue.
If you would add one more parameter c,idx. Map function will get currentvalue and index inside it.
var animals = ["cat","dog","fish"];
var lengths = animals.map(function(c, idx, arr, test) {
console.log(c); // currentvalue being processed in the array.
console.log(idx); // index of currentvalue in the array
console.log(arr); // original array being operated on.
console.log(test); // undefined always. not available in map.
return c.length;
});
console.log(lengths);//[3, 3, 4]
I know this is a silly question so please go easy.
I'm having trouble understanding documentation in general such as this page:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Can someone explain the terms 'callback' 'currentValue' 'index' 'array' (in that context) and 'thisArg' in very basic layman's? I'm sure it's something simple but it's just not clicking in my brain, and it's making learning the language on my own very difficult so I would greatly appreciate the help.
I'll try to make it very simple and understandable.
A callback function is passed as an argument to a function (like age is passed to foo in the example below) and is executed after a certain event. It is called callback because it is executed not before the parent function (to which the callback function was passed to as an argument) itself is executed.
For example:
function foo(age, function callBack()) {
print("I am " + age + " years old");
}
function gender() {
print(" and male");
}
function certainEvent() {
foo(99, gender);
}
If you now call certainEvent(), the result would be:
I am 99 years old and male
callback is a function that you pass to map. It will be called with the arguments currentValue, index and array.
For instance using a callback that logs:
[1, 2, 3].map(function(currentValue, index, array) {
console.log("currentValue", currentValue);
console.log("index", index);
console.log("array", array);
});
Logs:
currentValue 1
index 0
array [1, 2, 3]
currentValue 2
index 1
array [1, 2, 3]
currentValue 3
index 2
array [1, 2, 3]
Note that the function doesn't have to inline, this is equal:
function mapper(currentValue, index, array) {
console.log("currentValue", currentValue);
console.log("index", index);
console.log("array", array);
}
[1, 2, 3].map(mapper);
.map is a function. Function usually accept arguments. The part you are referring to describes the arguments and their purpose in more detail. Lets have a look at the signature of the function:
arr.map(callback[, thisArg])
This tells you that the function takes two arguments, where the second argument is optional (indicated by the [...]).
The documentation chose to name the first argument "callback" and the second argument "thisArg". It could have chosen different names ore no names at all and simply referred to the "first" and "second" argument.
Of course the chosen names carry some meaning, but this is only secondary. Naming them at all is done to be able to easily refer to those arguments later in the documentation. Whenever you see callback (i.e. formatted as code) in the documentation for .map, such as
Value to use as this when executing callback.
you know that it refers to the first argument.
Similarly "currentValue", "index" and "array" are labels for the arguments that are passed to the first argument of .map ("callback"), since that argument is supposed to be a function as well.
currentValue by itself doesn't really mean anything. However, in the context of .map it refers to the first argument that is passes to the first argument of .map. It's meaning is described in the documentation:
The current element being processed in the array.
This follows the typical way we write functions. When you declare a function, you usually give the parameters names. For example:
function first(arr) {
return arr[0];
}
Here I am giving the first parameter the name arr so I can refer to it more easily later. The same happens in the documentation: The parameter/argument gets a name so it can easily be referred to later.
The map method has two arguments. The callback and the scoping parameter.
The callback is the function that you set that does the processing. It has three arguments that give you the state of the current iteration as map loops over the array.
var myArray = [1,2,3,4,5];
function callback ( currentValue, index, array) {
console.group("callback called");
console.log("currentValue:", currentValue); //Current value of the index aka `array[index]`
console.log("index:", index); //current index of the loop (think of it as a for loop (var i=0; i<array.lenght; i++) It would be i.
console.log("array:", array); //The array you are looping over..aka a reference to myArray
console.groupEnd("callback called");
return currentValue * 2;
}
var result = myArray.map(callback);
console.log(result);
And the [] in the method declaration [, thisArg] states that that parameter/argument is optional.
If there's anyone who can help me understand this one, I will be impressed. It's #28 from John Resig's advanced JavaScript.
Here's a function for looping, and, if you look at the tutorial, it seems to run 3 times producing the 6 Pass below.
Can you please explain in plain language in as much detail as possible what is happening in this program, explaining along the way:
fn.call(array, array[i], i) Why are there these 3 parameters to the function and how do they all work. Does the function first deal with array, then array[i], and then i? What's happening when all that is going on?
Also, in the function, I understand that i++ goes up every time that it goes through the array.length, but what triggers num++ to increase it's value, and in what way is value == num++
In function(value, i), what is value? Is value alternately 0,1,2 of the loop array? If so, how do those loop array numbers get passed as a parameter in function(value, i)
this instanceof Array what is this trying to show? How?.
Code:
function loop(array, fn){
for ( var i = 0; i < array.length; i++ )
fn.call( array, array[i], i );
}
var num = 0;
loop([0, 1, 2], function(value, i){
assert(value == num++, "Make sure the contents are as we expect it.");
assert(this instanceof Array, "The context should be the full array.");
});
PASS Make sure the contents are as we expect it.
PASS The context should be the full array.
PASS Make sure the contents are as we expect it.
PASS The context should be the full array.
PASS Make sure the contents are as we expect it.
PASS The context should be the full array.
The function is an anonymous function, that is, a function without a name. The full second argument to loop is
function(value, i) {
assert(value == num++, "Make sure the contents are as we expect it.");
assert(this instanceOf Array, "The context should be the full array.");
}
which is a complete anonymous function which takes three arguments: this (the object for which it is a method), the current value, and the loop counter.
loop iterates over the array, and uses fn.call to invoke the anonymous function, passing it three arguments; here, the array object must be explicit, because call can't know what context the function reference it's being invoked on should be invoked in (that is, what to make this in the call).
The anonymous function, as invoked by loop, receives the array as this. The second ASSERT verifies this. It also expects that the array's value is [0, 1, 2] and verifies this by incrementing num on each call and comparing that to the passed array element.
So, following the execution chain:
num is declared and initialized to 0.
loop([0, 1, 2], function ...) is invoked.
loop invokes fn, the anonymous function, with the array (as this), its first element, and i which indicates the element offset. (i is never actually used.)
The anonymous function ASSERTs that it was passed the expected first element, 0, by comparing against num and incrementing num afterward.
The anonymous function ASSERTs that its this is an Array.
loop invokes fn as in #3, but with the second array element.
The anonymous function again performs its ASSERTs, this time comparing the passed second array element, which is expected to be 1, against num (which, because of the post-increment in step 4, is 1).
loop invokes fn as before with the third array element.
The anonymous function does its ASSERTs again, this time comparing the expected array element 2 against num whose value is now 2.
fn is a function pointer to the anonymous function that was created when invoking loop.
a) There are three parameters because the first one is a reference to the object you are going to be acting on, i.e. the array, the 2nd parameter is just current value in the iteration of the array, and the third value is location of that element in that array.
b) when you call num++, it increments the value of num. The post increment returns the value (aka assigns to value) and then increments num.
c) value is the 2nd parameter passed in by fn.call a couple lines up.
d) this refers to the array that you passed into the first parmater in your fn.call() invocation.
I think an easier way to understand what's going on is to remove the usage of call and instead invoke the method directly - the old fashioned way.
function loop(array, fn) {
for(var i = 0; i < array.length; i++)
fn(array[i], i);
}
var num = 0;
loop([0, 1, 2], function(value, i) {
assert(value == num, "Make sure the contents are as we expect it.");
assert(this instanceof Array, "The context should be the full array.");
num++;
});
If you run this code on the source url, you would see the this instanceof Array test fails each time, since this is not pointing to an instance of Array anymore.
To make this point to an instance of Array, we need to invoke the method using call or apply.
fn.call(array, array[i], i);
The first parameter is what this will point to. All other parameters here are passed as arguments to the function being called. Note that we can cheat here to pass the test. Instead of passing the array object that we are looping over, you can pass any Array object to make the second test pass.
fn.call([], array[i], i);
fn.call([1,2,3,4,5], array[i], i);
I don't actually know javascript but I believe I understand whats going on...
The first four lines are defining a function called loop. Loop takes in two variables, an array and a function. The only reason why I believe the second parameter is function is because the coder called call on the variable which probably calls the function. The function loops through the elements of the array and passes them to the function somehow through the call method. You should probably look this part up.
After the definition, num is defined to start at zero.
Then comes the fun part. The function loop is called with the parameters [0, 1, 2] and an anonymous function that was created on the spot. function(value, i) and everything after it is the definition of this anonymous function. It has no name but it just defined for this function call. The function checks to make sure that value equals num and increments num after it and then checks to makes sure the variable is an array.