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);
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.
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;
};
A general question on JavaScript. If I have a function which modifies an array, such as:
var some_array = [];
function a_function(input, array){
//do stuff to array
return array;
}
In most languages:
var some_array = [];
some_array = a_function(input, some_array);
console.log(some_array);
works, however in js the below works as well:
var some_array = [];
a_function(input, some_array);
console.log(some_array);
Is this correct and how is this working?
Arrays in JS are objects and are passed into functions by value, where that value is a reference to the array. In other words, an array passed as an argument to a function still points to the same memory as the outer array.
This means that changing the array contents within the function changes the array passed from outside the function.
function f(arr) {
arr.push(1);
return arr;
}
var array = [];
// both function calls bellow add an element to the same array and then return a reference to that array.
// adds an element to the array and returns it.
// It overrides the previous reference to the array with a
// new reference to the same array.
array = f(array);
console.log(array); // [1]
// adds an element to the array and ignores the returned reference.
f(array);
console.log(array); // [1, 1]
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 trying to write a currying function in JavaScript,the inner function does not update the value of the array args:
var myCurry=function(fn)
{
var len=fn.length;
var _slice=Array.prototype.slice;
var args=_slice.call(arguments,1);
console.log(args.length);
return function next()
{
var rem=_slice.call(arguments,0)
args.concat(rem);
console.log(args.length);
if(len<=args.length)
return fn.apply(null,args);
else
return next;
}
}
I call it like this:
var _sum=myCurry(sum,2);
var res=_sum(2);
var res2=res(3,4);
console.log(res2);
This returns the function next at all times,presumably because the array is not updated.How do I fix this error to ensure that the function work?
It's because .concat() doesn't mutate the array. Use .push() instead if you want to mutate the original.
args.push.apply(args, rem);
Or if you didn't care if the original was replaced, just assign the return value from .concat()
args = args.concat(rem);
Oops:
args.concat(rem);
Instead:
args = args.concat(rem);
concat() performs no in-place modifications. It returns a new Array