Recursive javascript function returns undefined [duplicate] - javascript

For some reason the method getTwo() inside the PollClass won't return 2 but undefined. If I put the return statement outside the .forEach() loop a value does get returned however.
class Poll {
constructor(name) {
this.name = name;
this.nums = [1, 2, 3];
}
getTwo() {
this.nums.forEach(num => {
if (num === 2) return num;
})
}
}
const newPoll = new Poll('random name');
console.log(newPoll.getTwo()); // returns undefined, not 2
Is this an issue with closure, ES 6, or a whole other issue?

An arrow function is still a function, and you're only returning from the forEach callback function, not from getTwo, you have to return from the getTwo function as well.
It's not quite clear why you would use a loop to check for something in that way, but the concept would be something like
getTwo() {
var n = 0;
this.nums.forEach(num => {
if (num === 2) n = num;
})
return n; // returns something from getTwo()
}

As adeneo mentioned, you must return from the getTwo function to achieve what you want. Returning from the callback passed into forEach, regardless if its an arrow function or not, doesn't return from forEach itself.
Alternatively to forEach, you can use find which you can write in less code and return directly:
getTwo() {
return this.nums.find(num => num === 2);
}

Related

I keep getting "undefined" as an error, function not returning anything

I've been trying to figure out why I keep getting undefined, and I don't really see why, I know that I would get undefined if my function isn't returning anything, but in this case, even with returning in two places, I am still getting undefined. I think that the reason for that is that maybe I am not returning the value from innerFunc properly? I'm thinking maybe there's something wrong with my syntax here: innerFunc(arg) but I'm not sure how it is wrong, or what to change it to.
Any help would be appreciated.
Instructions:
Create a function "fastCache" that takes one argument (a function) and returns a function. When fastCache is invoked it creates an object that tracks calls to the returned function, where each input to the returned function is associated with its output. Every subsequent call to that returned function with the same argument will return the output directly from the object, instead of invoking the original function again.
function fastCache(func) {
const obj = {};
function innerFunc(arg) {
for (const key in obj) {
if (key === arg) {
return obj[arg]
} else {
obj[arg] = innerFunc(arg)
return innerFunc(arg)
console.log(obj[arg])
console.log(arg)
console.log(innerFunc(arg))
}
}
}
return innerFunc
// console.log(innerFunc(arg))
}
//example:
//SINGLE ARGUMENT CASE
const multiplyBy2 = num => num * 2;
const cachedMultiplyBy2 = fastCache(multiplyBy2);
If you want a simple cache function:
function cacheWrapper(fn) {
let cache = { };
return arg => {
if (cache.hasOwnProperty(arg)) {
return cache[arg];
}
return cache[arg] = fn(arg);
};
}
function test(x) {
return x * 2;
}
let testCached = cacheWrapper(test);
console.log(testCached(2));
console.log(testCached(2));
The key here is hasOwnProperty which will tell you if that cache slot is occupied or not. This avoids having to fumble around and find out the hard way with iteration.
If the number isn't already in the object, it won't be found in the loop.
function fastCache(func) {
const obj = {};
function innerFunc(arg) {
for (const key in obj) {
if (key === arg) {
return obj[arg]
}
}
obj[arg] = func(arg)
return func(arg)
}
return innerFunc
// console.log(innerFunc(arg))
}
//example:
//SINGLE ARGUMENT CASE
const multiplyBy2 = num => num * 2;
const cachedMultiplyBy2 = fastCache(multiplyBy2);
const result = cachedMultiplyBy2(8);

How this parameter knows the argument

Im confused with how the elem get the value of arr?
function lengGreaterThan(num) {
function lengGreaterThanNum(elem) {
return elem.length > num;
}
return lengGreaterThanNum;
}
let arr = ['Justin', 'caterpillar', 'openhome'];
console.log(arr.filter(lengGreaterThan(6)));
That is a really confusing way of writing it, but essentially you are just putting a function that takes one parameter into the filter function.
This here would do the same thing:
console.log(arr.filter((elem) => {
return elem.length > 6;
}));

JS callback function issue?

I'm attempting to create a function which accepts an array and a callback function. The function should return true if all values in the array passed to the callback return true, otherwise, return false. But I'm not sure what I'm doing incorrectly
const every = function(arr, callback) {
arr.forEach(function(element) {
if(!callback(element)) {
return false
}
})
return true
};
every([1, 2, 3, 4, 5], function(val) {
return val < 2
});
expected results => false
but I'm getting true.
I would recommend using a simple for loop:
const every = (arr, callback) => {
for (let i = 0; i < arr.length; i++){
if (callback(arr[i]) === false){
return false;
}
}
return true;
};
console.log(every([1, 2, 3, 4, 5], function(val){return val < 2}));
Returning false from the forEach callback will not also cause the every function to return. Instead it will simply continue the forEach iterator.
The most easy solution to your problem would be a for...of loop, since it allows you to use a return pattern similar to your snippet:
const every = function(arr, callback) {
for (const element of arr) {
if (!callback(element)) {
return false;
}
}
return true;
};
console.log(every([1, 2, 3, 4, 5], function(val) {
return val < 2;
}));
Note: By using a loop construct every returns early. The forEach method of arrays always runs until all array elements are visited, but the loop breaks immediately after one element fails the test. A regular for loop would give you the same performance benefit.
You could potentially use reduce() for this. If you base your reduction on the truth and the result of the callback, it will remain true so long as the callback is true. Once a callback is false, the check for truth in the conditional will short circuit the logic and the callback will not execute anymore. It will loop through all the elements though.
It also returns true for an empty array, which seems to match your original logics intent.
const every = function(arr, callback) {
return arr.reduce(function(truth, element){
return truth && callback(element);
}, true);
};
console.log(
every([1, 2, 3, 4, 5], function(val){return val < 2})
);
console.log(
every([], function(val){return val < 2})
);
arr.forEach(function(element) {
return false
})
Its the inner function returning false, which have no effect for the outer function (in this situation)
you should create a new variable inside the outer function and instead of returning false in the inner function, change the variable
at the end just return the variable
const every = function(arr, callback) {
let isEvery = true
arr.forEach(function(element) {
if(!callback(element)) { // or just isEvery = isEvery && statement
isEvery = false
}
})
return isEvery
};

Javascript function call with another function as parameter

I have a few functions in two different files that are all linked together by function calls they are as follows
FILE 1:
function getFunction(func){
}
FILE 2:
function Numbers(one, two) {
return (one*two);
}
var func = getFunction(Numbers);
and these are called by:
func(input_array);
my array has values 1,3,5,7,9 and I need func(input_array) to return 3,15,35,63,9 (the last value loops back to the first value)
basically what I am trying to do is have getFunction return a function such that these values are calculated. I am having trouble because I can't wrap my mind about sending and returning functions. I don't know how to access the array if it isn't sent into the function. Let me know if I need to clarify anything.
function getFunction(callback) {
return function(array) {
return array.map(function(cur, index) {
return callback(cur, array[(index+1) % array.length]);
});
};
}
getFunction returns a closure over the callback parameter, which is the function that you want to call. The closure receives the array parameter, and it calls the callback in a loop over the array using array.map. The % modulus operator performs the wraparound that you want.
Another way to write this that may be clearer is:
function getFunction(callback) {
return function(array) {
var result = [];
for (var i = 0; i < array.length; i++) {
j = (i+1) % array.length; // Next index, wrapping around
result.push(callback(array[i], array[j]));
}
return result;
};
}
var func = getFunction(Numbers);
console.log(func([1,3,5,7,9])); // Logs [3,15,35,63,9]
here is simple function that returns what you need
function Numbers(x) {
output_array=[];
for(i=0;i<x.length;i++){
if(x[i+1]==undefined){
output_array.push(x[i]);
}
else{
output_array.push(x[i]*x[i+1]);
}
}
return output_array;
}
var input_array=[1,3,5,7];
var num = Numbers(input_array);
console.log(num);
OR if you need it in the way function calling another function
and than returning the result use this
function getFunction(Numbers,input_array){
return Numbers(input_array);
}
function Numbers(x) {
output_array=[];
for(i=0;i<x.length;i++){
if(x[i+1]==undefined){
output_array.push(x[i]);
}
else{
output_array.push(x[i]*x[i+1]);
}
}
return output_array;
}
var input_array=[1,3,5,7];
var num = getFunction(Numbers,input_array);
console.log(num);

Why does this forEach return undefined when using a return statement

Object.prototype.e = function() {
[].forEach.call(this, function(e) {
return e;
});
};
var w = [1,2];
w.e(); // undefined
But this works if I use alert instead
// ...
[].forEach.call(this, function(e) {
alert(e);
});
// ...
w.e(); // 1, 2
I realize this is an old question, but as it's the first thing that comes up on google when you search about this topic, I'll mention that what you're probably looking for is javascript's for.. in loop, which behaves closer to the for-each in many other languages like C#, C++, etc...
for(var x in enumerable) { /*code here*/ }
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/for...in
http://jsfiddle.net/danShumway/e4AUK/1/
A couple of things to remember :
for..in will not guarantee that your data will be returned in any particular order.
Your variable will still refer to the index, not the actual value stored at that index.
Also see below comments about using this with arrays.
edit: for..in will return (at the least) added properties to the prototype of an object. If this is undesired, you can correct for this behavior by wrapping your logic in an additional check:
for(var x in object) {
if(object.hasOwnProperty(x)) {
console.log(x + ": " + object[x]);
}
}
Your example is a bit odd, but as this question is becoming the canonical "return from forEach" question, let's use something simpler to demonstrate the problem:
Here, we have a function that checks the entries in an array to see if someProp matches value and, if so, increments the count on the entry and returns the entry:
function updateAndReturnMatch(array, value) {
array.forEach(function(entry) {
if (entry.someProp == value) {
++entry.count;
return entry;
}
});
}
But calling updateAndReturnMatch gives us undefined, even if the entry was found and updated.
The reason is that the return inside the forEach callback returns from the callback, not from updateAndReturnMatch. Remember, the callback is a function; return in a function returns from that function, not the one containing it.
To return from updateAndReturnMatch, we need to remember the entry and break the loop. Since you can't break a forEach loop, we'll use some instead:
function updateAndReturnMatch(array, value) {
var foundEntry;
array.some(function(entry) {
if (entry.someProp == value) {
foundEntry = entry;
++foundEntry.count;
return true; // <== Breaks out of the `some` loop
}
});
return foundEntry;
}
The return true returns from our some callback, and the return foundEntry returns from updateAndReturnMatch.
Sometimes that's what you want, but often the pattern above can be replaced with Array#find, which is new in ES2015 but can be shimmed for older browsers:
function updateAndReturnMatch(array, value) {
var foundEntry = array.find(function(entry) {
return entry.someProp == value;
});
if (foundEntry) {
++foundEntry.count;
}
return foundEntry;
}
The function e() isn't returning anything; the inner anonymous function is returning its e value but that return value is being ignored by the caller (the caller being function e() (and can the multiple uses of 'e' get any more confusing?))
Because
function(e) {
return e;
}
is a callback. Array.forEach most likely calls it in this fashion:
function forEach(callback) {
for(i;i<length;i++) {
item = arr[i];
callback.call(context, item, i, etc.)
}
}
so the call back is called, but the return doesn't go anywhere. If callback were called like:
return callback.call();
the it would return out of forEach on the first item in the array.
You can use for...of to loop over iterable objects, like array, string, map, set... as per Mozilla docs.
const yourArray = [1, 2, 3]
for (const el of yourArray) { // or yourMap, Set, String etc..
if (el === 2) {
return "something"; // this will break the loop
}
}

Categories