Hello I am new this is my first question. I am completing the JavaScript Primer for Bloc, and am stuck on a simple checkpoint.
I am trying to Create a function named arrayLengthPlusOne. This function should: take one argument, an array return a number that is one greater than the number of elements in the array.. For example: arrayLengthPlusOne([0,0,1,0,2,1]); // returns 7
code i tried:
var arrayLengthPlusOne = function () { return arrayLengthPlusOne.length + 1; };
I am getting an error message telling me it isnt' passing tests. Maybe i'm not grasping the array/function relationship. I understand that an array is an Object not a Data Type. How do i make my function take one argument, that IS an array ?
Only you need to add an argument in your function declaration.
var arrayLengthPlusOne = function(data) { // data is an argument in the function. It's an array.
return data.length + 1;
};
// Calling the function.
var arrayData = [0, 1, 3, 4]; // Declare an array variable with four elements.
alert(arrayLengthPlusOne(arrayData)); // Show an alert with the result. Returns 4 + 1 elements.
The problem is your variabel name "arrayLengthPlusOne" in the function.
You should do something like:
var arrayLengthPlusOne = function (yourArray) { return yourArray.length + 1; }
and the call the function
myArray = [1 ,2 ,3 ,4 ]
arrayLengthPlusOne(myArray)
you need to pass the array as a parameter
var arrayLengthPlusOne = function(array) {
return array.length + 1;
}
Inside the function you can check whether the parameter passed is an array or not. If the parameter is an array it returns the length added by 1. If it's not an array, it returns undefined. However you can change the return type based on your requirement
var arrayLengthPlusOne = function (array1) {
if (array1 instanceof Array) {
return array1.length + 1;
}
};
You are missing to pass the arguments to the function.
Try this one:
alert(arrayLengthPlusOne([1,2,3,4,5,6]));
var arrayLengthPlusOne = function (myArray) {
return myArray.length + 1;
};
Related
I'm trying to use Closure in JS in order to declare a function named **expandArray()** which contain an Array named **myArray**and Returns an anonymous function that directly modifies myArray by increase the values by 1 than the returned function then returns the value of **myArray**. My Problem here one the last part where the returned function return a function not Array value ?!
This is my code
function expandArray() {
const myArray = [1, 1, 1];
return function () {
myArray.forEach( function (num, index, myArray) {
myArray[index] = num + 1;
});
return myArray;
};
}
console.log(expandArray());
As its closure, you have invoked it only once like expandArray() , which return the function itself, which is below
ƒ () {
myArray.map( function (num, index, myArray) {
myArray[index] = num + 1;
});
return myArray;
}
you need to invoke it again to get your result back as below
expandArray()() //[2, 2, 2]
Ref: How do JavaScript closures work?
You've written a function that returns a function when you run it:
function expandArray() {
const myArray = [...];
// return this when we run expandArray():
return function() {
...
}
}
So if you run expandArray(), it is going to return your anonymous function. Exactly as you wrote it to do.
If you then want to get an actual reference to that internal myArray, you'll now need to actually run that returned function, so:
var getMyArray = expandArray();
var result = getMyArray();
console.log(result);
Just fyi, you are doing something very similar to the memoization pattern.
To address your problem: as everyone else has already said, you return a function from expandArray. What you want is to return the closed array (after incrementing every element).
To do this, you can use something called immediately-invoked function expression in combination with arrow functions to simplify your code:
const expandArray = (() => {
const myArray = [1, 1, 1];
return () => {
myArray.forEach((num, index) => {
myArray[index] = num + 1;
});
return myArray;
};
})();
console.log(expandArray());
console.log(expandArray());
console.log(expandArray());
There are a couple of things incorrect with your code.
you can't change the values of variables declared within const. In the case of Objects and Arrays, you aren't allowed to assign a new reference with a new Array or Object. We change the declarative operator to let instead of const.
myArray.map doesn't mutate myArray, it returns a new array based on the input from myArray and your passed in function that adds 1 to each value. We can fix this by assigning myArray.map to the already declared myArray. That is to say, we're overwriting the old Array with a new one. This is why const in the above bullet point won't work.
Your map function parameters are unnecessary The parameters for it that are most often used are the first two available, which is the item in the array and the index of that item. Since we're iterating over each number using map the function can simply return the item (declared as num in your code) plus 1. This will return a new array with your changed values. So we don't need the index at all..
When you return a function from a function you need to invoke both to get the second return value. When using a closure you need to keep a reference to the initial returned function. This is confusing but if you think of it as levels - in your expandArray function you have two levels. The function itself and the function you're returning. when you call expandArray() you're invoking the first level, and making the second level available to be invoked, this is why expandArray() returns the second function and expandArray()() will return the value from the second function. We save the returned function in a variable called add_to_array by setting it equal to expandArray(), and then we consistently invoke add_to_array to return the new Array with the changed values.
This is the most confusing part of closures, but what is happening is that the add_to_array variable is like a wedge in the function. It stops myArray from being deleted by the Browser because it requires the function to exist in the event that it needs to be invoked again. It's kind of like a bookmark in a book. For the story to make sense whenever you open it, you don't just tear out the pages before the bookmark. You keep the story intact because in five years when you come back to it you may need to read the previous pages at the bookmark to remember where you were. A closure works the same way. It can't remove the variables from the initial expandArray function call because add_to_array is a placeholder in the middle of it. The reference point keeps the book open.
(for more info on closures you can check out this article here Destroying Buildings - A Guide to JavaScript Closures)
function expandArray() {
let myArray = [1, 1, 1];
return function () {
myArray = myArray.map( function (num) {
return num + 1;
});
return myArray;
};
}
let add_to_array = expandArray();
console.log( add_to_array(),add_to_array(),add_to_array() );
In your original code, you're only getting the return value of expandArray(), which is the function you're trying to use as a closure. In order to get the closure's return value, try this out:
function expandArray() {
const myArray = [1, 1, 1];
return function () {
myArray.forEach( function (num, index, myArray) {
myArray[index] = num + 1;
});
return myArray;
};
}
console.log(expandArray()());
The second set of parentheses after the call to expandArray() will invoke the closure and return the values you're seeking.
Old post, but I still like to contribute. I came up with this solution, as I think you want add something to the array instead of incrementing the numbers.
function expandArray() {
let myArray = [1, 1, 1];
return function() {
myArray.push(1)
return myArray
}
}
const array = expandArray();
const result = array();
console.log(result)
3years after this question was posted this lines of code works fine for me
function expandArray() {
let myArray = [1, 1, 1];
return function() {
myArray.push(1);
return myArray;
};
}
let newArray = expandArray();
console.log(newArray());
Note this is my first contribution on stack overflow.
Hi I'm trying to learn how to implement callback functions. My teacher has helped me out multiple times but I still can't pass data through the following equation below. I'm trying to get certain elements of array to get pushed into a new function if only they pass a test within the function. Please have a look and thank you for your input. An explanation as to why I get an empty array and resources to further my understanding would be appreciated.
// EACH DEFINITION
function each (collection, callback) {
for(var i = 0; i < collection.length; i ++){
callback(collection[i]);
}
}
// VARIABLE DECLARATION
var myArray = [1,2,3,4,5,6];
var isEven = function (num) {
return num % 2 === 0;
};
// IMPLEMENT DEFINITION
function implement(array, test){ // array = myArray, test = isEven
var arr = [];
each(array, function(item){
test(item);
});
if(test(array)){
arr.push(array);
}
return arr;
}
// IMPLEMENT INVOCATION
implement(myArray, isEven);
You are building arr outside the each() loop.
I would think your code would be like this:
// IMPLEMENT DEFINITION
function implement(array, test){ // array = myArray, test = isEven
var arr = [];
each(array, function(item){
if(test(item)) {
arr.push(item);
}
});
return arr;
}
Though in this case there is no reason for your implement() filtering function at all, since javascript Array prototype already has a filter method. You could simplify your call to this:
var filteredArray = myArray.filter(isEven);
Though you might also then want to change your isEven definition to be more correct as:
var isEven = function (num, index, array) {
In your case you don't need to work with the last two parameters.
// EACH DEFINITION
function each (collection, callback, results) {
for(var i = 0; i < collection.length; i ++){
callback(collection[i]);
}
console.log(results);
}
// VARIABLE DECLARATION
var myArray = [1,2,3,4,5,6];
var isEven = function (num, array) {
return num % 2 === 0;
};
// IMPLEMENT DEFINITION
function implement(array, test){ // array = myArray, test = isEven
var arr = [];
function filter (item) {
if (test(item)) {
arr.push(item);
}
}
each(array, filter, arr);
// If you return arr here, it will still be empty. You must pass it to functions it is being operated on.
}
// IMPLEMENT INVOCATION
implement(myArray, isEven);
Not only are you trying to push to arr outside of your loop, but you're trying to return arr before it has gained any values.
Two points:
First, your implementation of callback functions is correct. As far as the concept of callbacks goes, you are calling and passing the functions correctly.
However, your implement() function probably has a bug. You are not pushing to arr until after each() has already been called:
function implement(array, test) { // array = myArray, test = isEven
var arr = [];
each(array, function(item) {
result = test(item);
});
// This block should be in the loop itself
// It should also refer to item, not array
if (test(array)) {
arr.push(array);
}
return arr;
}
Try this fix based on the code you provided:
// EACH DEFINITION
function each(collection, callback) {
for (var i = 0; i < collection.length; i++) {
callback(collection[i]);
}
}
// VARIABLE DECLARATION
var myArray = [1, 2, 3, 4, 5, 6];
var isEven = function(num) {
return num % 2 === 0;
};
// IMPLEMENT DEFINITION
function implement(array, test) { // array = myArray, test = isEven
var arr = [];
each(array, function(item) {
if (test(item)) {
arr.push(item)
}
});
if (test(array)) {
arr.push(array);
}
return arr;
}
// IMPLEMENT INVOCATION
var result = implement(myArray, isEven);
console.log(result); // For snippet results
Your callback, as you defined it, is
function(item){
test(item);
}
this will only call test on each item and that's it. Since you want to take it further and add item to arr if test returns true, you should put that checking code inside the callback as well, making it
function(item){
if (test(item)) {
arr.push(item);
}
}
so that this function will be called for each of the item.
Also, this part
if(test(array)){
arr.push(array);
}
is incorrect because you are passing a whole array into isEven when isEven is expecting a number. test(array) will always return false; that's why your arr is empty.
Modifying your code to work as you wanted, it would be
// IMPLEMENT DEFINITION
function implement(array, test){ // array = myArray, test = isEven
var arr = [];
each(array, function(item){
if (test(item)) {
arr.push(item);
}
});
return arr;
}
Resources wise, there are callbacks tutorial widely available online, as well as best practices. You can easily find one that suits you best by googling.
It looks to me like the entire issue here is in the implementation section you denote. All of the other code looks adequate.
each(array, function(item){
test(item);
});
Alright, first let's examine this piece of code. You are making a call to your each function, which will use the callback anonymous function defined here as shown.
However, if you were to look at the each function itself, there is no return (which means it returns undefined by default). There is also no modification being done in each. As a result, this set of code has no effect on the execution of the code, and from certain advanced compilation technique may actually be removed by the V8 engine in chrome if that was being used.
This means the only aspect of your code which is executing is
var arr = [];
if(test(array)){
arr.push(array);
}
return arr;
At this point, test is still the isEven function, so you are basically asking this
if(array % 2 === 0) arr.push(array);
Arrays in JavaScript behave interestingly when used in conditional statements, and in this situation the array essentially has toString called on it (more in depth here: https://stackoverflow.com/a/10556035/1026459 , but basically when you have object === number then it will attempt to use toPrimitive on the object which results in a string), which makes it
if("1,2,3" % 2 === 0)
which is false. As a result arr is unchanged, and returned in its original state of [].
I'm trying to return an array from a function and work with its results.
When I just want to get its length, I always get a 0:
function myFunc() {
var arr = [];
arr.push("test");
arr.push("another test");
return arr;
}
alert(myFunc.length) // expected 2, but got 0
Here is a fiddle.
You need to call it as myfunc().length because you are calling a function.
Remember you are calling a function, so the parameter list (even if empty) must be given to the call, try:
alert(myFunc().length)
You have to call the function like so
function myFunc() {
var arr = [];
arr.push("test");
arr.push("another test");
return arr;
}
alert(myFunc().length)
https://jsfiddle.net/n5xdcrzm/
Function.length, The length property specifies the number of arguments expected by the function.
And that is the reason you could get 0 in alert as you are reading length property of the function-object
If you are expecting 2, which is length of the array, you need to invoke the function.
function myFunc returns the array in which 2 items are being pushed.
Invoke the function and read the length property of the returned array
function myFunc() {
var arr = [];
arr.push("test");
arr.push("another test");
return arr;
}
alert(myFunc().length);
As others have mentioned this code comes from chapter 6 of eloquent javascript. I do not understand where the arguments to the function 'drawRow' are supplied from. If the outer function drawTable were some sort of method it would make sense that it could pass an array as well as the current index, but it's not. It's just an ordinary function so where does it grab 'row' and 'rowNum' from?
function drawTable(rows) {
var heights = rowHeights(rows);
var widths = colWidths(rows);
function drawLine(blocks, lineNo) {
return blocks.map(function(block) {
return block[lineNo];
}).join(" ");
}
function drawRow(row, rowNum) {
var blocks = row.map(function(cell, colNum) {
return cell.draw(widths[colNum], heights[rowNum]);
});
return blocks[0].map(function(_, lineNo) {
return drawLine(blocks, lineNo);
}).join("\n");
}
return rows.map(drawRow).join("\n");
}
Thank you in advance to anyone taking the time to answer this.
According to MDN Array.prototype.map, the callback supplied to map has three parameters: currentValue, index, and array. In this case, when drawRow is supplied to rows.map, row is the currentValue, and rowNum is the index.
Here's a simpler example:
var arr = ['a', 'b', 'c'];
function printArray(value, index) {
console.log(index + ' ' + value);
}
arr.map(printArray);
// prints
// 0 a
// 1 b
// 2 c
The map function calls the provided callback (drawRow in your case) with three arguments for each element of the array that it is iterating over:
the element
the index
the whole array (which you are not making use of here)
You could optionally also set some object to become this inside of the callback.
As others have mentioned, the map method calls drawRow passing the appropriate values. To illustrate the mechanics behind this let's create another function, called M_A_P, from scratch that would also call drawRow with the appropriate values:
function M_A_P (theArray, callback) {
var returnArray = [];
for (var i=0; i<theArray.length; i++) {
var result = callback(theArray[i],i); // note this line
returnArray.push(result);
}
return returnArray;
}
The function M_A_P above calls a function we supply to it with two arguments, the value of one item from theArray (theArray[i]) and the index of the item (i).
Now, we can use M_A_P to process the rows:
M_A_P(rows, drawRow).join("\n");
Remember that the function drawRow will be passed in to M_A_P as the variable callback and the array rows will be passed in as the variable theArray. M_A_P then will call drawRow the way described above with two arguments.
The method Array.map() works similarly but implemented as a method of array objects instead of a function.
I am having problems understanding the concept of Array.map. I did go to Mozilla and Tutorials Point, but they provided very limited info regarding this.
This is how I am using Array.map. It is a little complex (a bit of d3.js involved; just ignore it)
var mapCell = function (row) {
return columns.map(function(column) {
return { column : column, value : getColumnCell(row, column) }
})
}
//getColumnCell is a function defined in my code
//columns is array defined at the top of my code
I do not understand exactly what this code is doing. I know its returning a new array and stuff but this part is a little tricky!
If you want to go through my code: http://jsfiddle.net/ddfsb/2/
I am using console to actually understand what's happening inside the code. Looking at the answers provided, I have clearly understood the concept of array.map. Now the only part remaining is parameters rows and columns, but there is a difference between row and rows, and column and columns in the fiddle provided
var rows//completely ok
var columns//completely ok
funcion(row)//here,source of row is unknown.getColumncell function utilizes this parameter further making it more critical
function(column)//source of column is unknown..getColumncell function utilizes this parameter further making it more critical
Let's rewrite it a bit, and start working from inside out.
var mapCell = function (row) {
return columns.map(
function(column) {
return {
column : column,
value : getColumnCell(row, column)
}
}
)
}
The function(column) part is essentially a function that takes a column as a parameter, and returns a new object with two properties:
column, that is the original value of the parameter, and
value, that is the result of calling the getColumnCell function on the row (external variable) and column (parameter)
The columns.map() part calls the Array.map function, that takes an array and a function, and runs the function for every last item of it, and returns the results. i.e. if the input is the array [1, 2, 3, 4, 5] and the function is something like isEven, the result will be the array [false, true, false, true, false]. In your case, the input are the columns, and the output is a list of objects, each of which has a column and a value properties.
Lastly, the var mapCell = function (row) part declares that the variable mapCell will contain a function of one variable called row - and this is the same row that is used in the inner function.
In a single sentence, this line of code, declares a function that when run, will take a row and return values for all columns for that row.
map loops through your original array and calls the method for each value in the array. It collects the results of your function to create a new array with the results. You are "mapping" the array of values into a new array of mapped values. Your code is equivalent to:
var mapCell = function (row) {
var result = [];
for (var i = 0; i < columns.length; ++i) {
var mappedValue = {
column: columns[i],
value : getColumnCell(row, columns[i])
};
result.push(mappedValue);
}
return result;
};
Understanding the map function is only part of the solution here, there is also the function mapCell. It takes one parameter row and it returns something like:
[ {
"column": "parties",
"value": [cell value]
}, {
"column": "star-speak",
"value": [cell value]
} ]
Where the cell value depends on the row and the column (parties, stars-speak etc.)
A map function applies a transformation to a value, and returns that transformed value.
A simple example:
function square(x) { return x * x; }
[ 2, 3, 4 ].map(square); // gives: [ 4, 9, 16 ]
Similarly:
[ "parties", "starspeak" ].map(function (column) {
return {
column: column,
value: findTheValue(column)
}
});
Now since that map is nested with a function that gets a row parameter. You can use it in the map function, to get:
function (row) {
return [ "parties", "starspeak" ].map(function (column) {
return {
column: column,
value: findTheValue(row, column)
}
});
}
And this gets pretty close to your code.
Map function goes through each element of an array in ascending order and invokes function f on all of them.
It returns new array which is being computed after function is invoked on it.
Syntax:
array.map(f)
Example:
<!doctype html>
<html>
<head>
<script>
var arr = [4,5,6];
document.write(arr.map(function(x){return x*2;}));
</script>
</head>
</html>
Answer: 8,10,12
Summary
Array.map is a function which is located on Array.prototype.map. The function does the following:
Creates a new array with the same amount of entries/elements.
Executes a callback function, this function receives and current array element as an argument and returns the entry for the new array.
Returns the newly created array.
Example:
Basic usage:
const array = [1, 2, 3, 4];
// receive each element of array then multiply it times two
// map returns a new array
const map = array.map(x => x * 2);
console.log(map);
The callback function also exposes an index and the original array:
const array = [1, 2, 3, 4];
// the callback function can also receive the index and the
// original array on which map was called upon
const map = array.map((x, index, array) => {
console.log(index);
console.log(array);
return x + index;
});
console.log(map);
Probably most people coming here (like me) just want a basic array.map usage example:
myArray = [1,2,3]
mappedArray = [];
mappedArray = myArray.map(function(currentValue){
return currentValue *= 2;
})
//myArray is still [1,2,3]
//mappedArray is now [2,4,6]
This is it at it's most basic. For additional parameers, check out: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
IF you have an array of elements and you have to perform the same operation on the
each element of the array that time you can use the javascript map function for array
it helps to iterate throw the array then we can perform the operation of each element and
return it.
let NumberArray = [1,2,3,4,5,6,7,8];
let UpdatedArray = NumberArray.map( (Num , index )=>{
return Num*10;
})
console.log(UpdatedArray);
//UpdatedArray ==> [10, 20, 30, 40, 50, 60, 70, 80]
Javascript map() Syntax
arrayObj.map(callback[,context]);
arrayObj is a original array on which map() is invoked.
The map() takes 2 named arguments, First is a callback function and the second is a context object. callback function gets triggered on every element of an array.
In addition, callback function takes 3 arguments:
function callback(currentElement,index,array){
}
currentElement – This is a current elements of array which is passed to callback function
index – Index of the current element
array – complete array on which map() is applied
Out of these 3 elements, currentElement parameter is mandatory while the rest 2 parameters are optional.
However, map() does not change the original array, it creates a new array element which is generated by callback function.
You can read more on JavaScript map function
Array map() method returns a new array.
It does not change the original array.
let array = arr.map((c, i, arr) => { //return element to new array });
here,
array is the new array that is returned.
arr is the original array on which the map method is called.
c is the current value that is being processed.
i is the index of current value.
For example:-
const originalArr = [4, 3, 2]; let newArr = originalArr.map((val) => val + val);
result:-
newArr: [8, 6, 4]
originalArr: [4, 3, 2]
in simple words you can perform operations on array using map
Examples
1.Array
let arr = ["sam","tom"]
console.log("Before map :",arr)
arr.map((d,i)=>{
arr[i] = d+"yy"
})
console.log("After map :",arr)
Examples
2.Array Of Objects
// console.log(Date.now());
let arr = [
{name:"sam",roll_no:10},
{name:"tom",roll_no:12}
]
console.log("Before map :",arr)
arr.map(d=>{
if(d.name == "sam")
{
d.name = "sammy",
d.roll_no=100
}
})
console.log("After map :",arr)