Do array elements have names by default in JavaScript? [duplicate] - javascript

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]

Related

Are there built-in parameters in Javascript? [duplicate]

This question already has an answer here:
What are Closures and Callbacks?
(1 answer)
Closed 4 months ago.
Where do arguments like element, index and array come from, for e.g. the filter method like below:
const arr = [ "Laurence", "Mike", "Larry", "Kim", "Joanne", "Laurence", "Mike", "Laurence", "Mike", "Laurence", "Mike" ];
const arr2 = arr.filter((value, index, array) => {
console.log(value, index, array.indexOf(value));
return array.indexOf(value) === index;
});
console.log(arr2);
In some built-in methods we use them, I know what they do, but I don’t understand if they are like built-in parameters.
For example, when one defines a function one would add parameters like value, index and array.
But when one calls the function one doesn’t add any arguments.
Are these kind of parameters like built-in parameters or why we don’t have to specify what they are?
I wrote a custom filter function to show you that these parameters aren't built-in, they are just passed to your callback by the Array.prototype.filter function when the internal loop is executed.
const result = filter([1, 2, 3, 4, 5], item => item % 2 === 0)
console.log(result)
function filter(array, callback) {
const newArray = []
for (let i = 0; i < array.length; i += 1) {
// pass value index and array
if (callback(array[i], i, array)) {
newArray.push(array[i])
}
}
return newArray
}
forEach example:
forEach([1, 2, 3, 4, 5], (value, index) => console.log(value, index))
function forEach(array, callback) {
for (let i = 0; i < array.length; i += 1) {
callback(array[i], i, array)
}
}
The answer is very simple, No there aren't
In JavaScript, functions are objects like any other -- you can pass functions to functions. This is how the Array.prototype.filter function (the filter method you'd call on an array like arr.filter(...)) works -- it takes a function as a parameter. It filters by calling the function you pass to filter, for every element, with the element [of the array] as value, the index of the element [in the array] as index, and the array itself as array. If your function returns true, the element is contained in the array returned by filter, otherwise the element isn't contained in the returned array.
So yes, the filter function is what calls the function you pass to filter, binding parameters to values -- something that makes parameters arguments.
In JavaScript, if you do not pass an argument to a function that expects an argument, the argument is undefined -- you can say that the parameter isn't bound:
function f(a) {
return a;
}
console.assert(f() === undefined); /// Yields true
JavaScript will not warn you that an argument is missing.
That is all there is to it, really.
Answering this question largely involves the difference between the terms "parameter" and "argument", also known as "formal parameters" and "actual arguments".
This canonical question, What's the difference between an argument and a parameter? covers the subject with external links.
Summary
A (formal) parameter is the name used when coding or documenting a function to identify an argument that will be passed to it.
An (actual) argument is the value of a (formal) parameter passed to a function when called.
Code that calls a function can supply arguments using literal values, or values held in variables or object properties. Calling code may choose to name variables after documented parameter names of a called function - but is not required to do so.
Posted code
arr.filter((value, index, array) => {
console.log(value, index, array.indexOf(value));
return array.indexOf(value) === index;
});
Here the array method Array.prototype.filter is called with a callback function argument, being the in-lined anonymous function, (value, index, array)=>{ /* code */}.
value, index and array are the call back function's parameter names, chosen by the person who wrote the code to be readable in English. If they wanted the code to be readable in French, say, they might have used elementCourant instead of value.
"value", "index" and "array" are the terms used in (MDN) English documentation of arguments passed to the callback by the filter method.
TL:DR
In general look up the documentation for standard JavaScript methods to find out what arguments are passed to callbacks they make. You can use callback argument names from the documentation as formal parameter names in callback functions you write - if you want to and it suits your purpose.

How to write a function to filter an array in javascript?

I'm wanting to write a function to filter objects of an array on some condition. I know that when you pass an array to a function, the changes you make to the array inside the function also change the array outside the function (if you are able to make the distinction in the first place anyway). For example,
a=[1,2,3]
function addItem(list){
list.push(4)
}
addItem(a)
// now a = [1,2,3,4]
Also, even though the filter method only returns a new array and doesn't change the array it was called it, it can be used to change that array by writing a = a.filter(someFunction). I imagine there is some subtlety I'm missing here because when I try to combine these two facts to write a function filtering an array on some condition, the original array isn't changed at all. Here is an example:
function isEven(n){
return (n%2 == 0)
}
function filterOdds(list){
list = list.filter(isEven)
}
a=[1,2,3,4]
filterOdds(a)
// a is still [1,2,3,4]
I suppose I really have two questions:
Why doesn't the above code change a to [2,4]? and
How can I write a function to filter lists as I'm trying to do above? Of course, you could get the job done without the function, but what I really want is to filter multiple arrays in a single function. This just seemed like the relevant simplification.
In your second code, you are reassigning the argument only. Reassigning a variable will, in almost all cases, have no side-effects; all it'll do is change what further references to that variable in that scope will refer to. If there happens to be an outer variable which gets passed as an argument, that outer variable will not get reassigned regardless of what happens inside the function, unless the function deliberately reassigns the outer references.
You could implement this by not passing the list argument - have filterOdds reassign the outer variable:
function isEven(n) {
return (n % 2 == 0)
}
function filterOdds() {
list = list.filter(isEven)
}
list = [1, 2, 3, 4]
filterOdds()
console.log(list);
If you want a more generic solution that'll work for any array passed, since dynamically reassigning an outer variable inside a function isn't possible, your only decent remaining option would be to return the new array and, when calling the function, assign the result:
function isEven(n) {
return (n % 2 == 0)
}
function filterOdds(list) {
return list.filter(isEven)
}
a = [1, 2, 3, 4]
a = filterOdds(a)
console.log(a);

JavaScript array as function input

I am be beginner in JavaScript, and do not know how to make a simple function with an array/vector as an input. This is the code I have:
function semGPA(credits) {
var c = credits.length;
return c;
}
I want to pass a list of numbers (ex. credits={3,4,5,6}), and have it tell me that there are 4 elements in the variable. So far, I have not found any built in functions that create a working function. Everything I try to use other than +-*/ results in a TypeError. Here it says the property "length" is undefined.
It's not entirely clear what you want. You can pass an array as credits and your function will work fine (although it's a bit pointless as is, since you can just directly call length on your array):
semGPA([1,2,3,4]); // returns 4
Perhaps you meant that you wanted to do something like this?
function semGPA() {
var c = arguments.length;
return c;
}
Which you can call like this:
semGPA(1,2,3,4); // returns 4
Which uses the arguments object which is a special object passed to functions that can be used to access all the arguments (including unnamed arguments) passed to a function.
As mentioned in the comments the example you have is an Object and not an array.
var array = [1,2,3,4,5]
var object = {1,2,3,4,5} ==> This is not a valid object in Javascript.
The object notation above expects a key-value pair. something like
var object = {1: 1, 2: 2, 3: 3}
The length property does not exist on an object. However, if you want to check the number of elements in an Object you can make use of the below code which is self explanatory:
var credits = {1:1,2:2,3:3,4:4}
function semGPA(credits) {
var creditKeysArray = Object.keys(credits); //this will give you an array of keys
var creditLength = c.length;
return creditLength;
}

javascript foreach with mysterious variable

I am trying to understand what this javascript does and I am looking at foreach and okay, I am guessing name variable is coming from the array. I can verify that from console.log. I can also verify, although I have no idea where it's coming from, that i is 0,1,2.
Can someone please point me to right direction of where this variable 'i' is coming from and how forEach works?
function getNames() {
var length = 0
, names = "";
['John', 'Susan', 'Joe'].forEach(function (name,i) {
length = i + 1;
names += name + ' '
})
return {
length: length,
names: names
}
}
undefined
console.log(getNames());
Object {length: 3, names: "John Susan Joe "}
undefined
If you look the docs properly it tells
The forEach() method executes a provided function once per array element.
ForEach takes a callback function which can take 3 parameters.
1) Current Value
2) Index of current value // which is 0,1,2
3) Array Itself.
So in following passes value of variables will be as bellow
1) name ==> 'john', i ==> index of 'john' which is 0
2) name ==> 'Susan', i ==> index of 'Susan' which is 1
3) name ==> 'Joe', i ==> index of 'Joe' which is 2
Any time in JS you see a function that you don't understand, google it on Mozilla Developer Network, like this "mdn forEach". If the function has a $ in it, you might look google it adding "jquery". In this case, though, it is a builtin and so we look it up with mdn. MDN is not the ultimate authority on Javascript, but it is a very good resource as it is maintained by Mozilla, known for their Firefox web browser.
From MDN Array.prototype.forEach
Summary The forEach() method executes a provided function once per array element.
Syntax arr.forEach(callback[, thisArg])
Parameters
callback Function to execute for each element, taking three arguments:
currentValue The current element being processed in the array.
index
The index of the current element being processed in the array.
array
The array that forEach is being applied to.
thisArg Optional. Value to
use as this when executing callback.
You have ['John', 'Susan', 'Joe'].forEach(function (name,i) so you will see that forEach is being called as a method on the Array ['John', 'Susan', 'Joe']. Here the argument to forEach( ) is an anonymous function with two parameters function(name,i){...}. This function is supplying the callback function mentioned in the docs. That supplied function will get called by forEach as many times as there are elements in the array. The docs say we will get 3 parameters, and in JS the 3rd parameter in this case (the array being modified) is being ignored as the function is written to only take two parameters.
So, matching up the parameters in the provided function with the specification, in this case name is going to be the current value from the array, and i the index number.
Note, though, that what to call the parameters in a function(param1,param2) is completely up to the developer. When reading someone else's code, you have to match up what they called param1 and param2 with what the specification or documentation for that feature says.
How foreach works is it takes a function as its argument. That function is then called for each element of the array with the following arguments function(current_value,current_index,original_array) for example you can do this.
var sumVal = 0,
sumInd = 0,
myArray = [2,4,6];
function sumValues(current){
sumVal += current;
}
function sumIndexes(notGonnaUse,index,o_array){
sumInd += index;
}
// the following is equivalent to calling sumValues three times
// sumValues(myArray[0], 0, myArray);
// sumValues(myArray[1], 1, myArray);
// sumValues(myArray[2], 2, myArray);
myArray.foreach(sumValues);
// sumVal is now equal to 2+4+6=12
// the following is equivalent to calling sumIndexes three times
// sumIndexes(myArray[0], 0, myArray);
// sumIndexes(myArray[1], 1, myArray);
// sumIndexes(myArray[2], 2, myArray);
myArray.foreach(sumIndexes);
// sumIndex is now equal to 0+1+2=2
In each case the function is passed all three arguments even though sumValues is defined to take only one argument. The remaining arguments can still be accessed using the arguments object.
Internally the function is free to call the arguments whatever it wants.
In the previous example we used named functions to pass to foreach, but in your example an anonymous function was passed
function (name,i) {
length = i + 1;
names += name + ' '
}
This function sets
name = current value
i = current index
it was also passed in the original array ['John', 'Susan', 'Joe'] as the third argument. Since it wasn't used the programmer didn't bother naming this argument. It can still be accessed however using arguments[2].

Mind boggling Function for Looping

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.

Categories