I have a Product javascript array, which contains all the products information.
Created a function which iterate on this array and find the product by matching id.
var products = JSON.parse('[{"Product":{"id":"1","name":"My Product","description":"This is my new product","price":"10.00","currency":"$","stock":"0","image":"/image1.png"}},{"Product":{"id":"5","name":"Dummy Product 2","description":"Some dummy text goes here.","price":"10.00","currency":"$","stock":"100","image":"image2.jpg"}}]');
$(document).ready(function(){
console.log(products);
alert(findProduct(5)); //it will returns false everytime, evan it has matching product
});
function findProduct(product_id){
$.each(products, function(k, v){
if(v.Product.id == product_id){
console.log(v);
return products[k]; //or return 'v'
}
});
return false;
}
Check this Demo
Function returns false each time, even though it found the matching product id, don't know why? If I store the matching array key in a variable and after iteration, return the value of that key it returns proper object. But that's not proper way, cause I want to stop iteration and return the value if object found.
You are always returning false from findProduct, if the item is found you are returning from the $.each() callback method, but that is not reflected in the value returned by findProduct method.
function findProduct(product_id) {
var found = false;
$.each(products, function (k, v) {
if (v.Product.id == product_id) {
console.log(v);
found = products[k];
//return false to prevent further iteration
return false;
}
});
return found;
}
Use this instead:
function findProduct(product_id){
var result = false;
$.each(products, function(k, v){
if(v.Product.id == product_id){
console.log(v);
result = products[k]; //or return 'v'
return;
}
});
return result;
}
And here is the problem:
function findProduct(product_id){
$.each(products, function(k, v){
if(v.Product.id == product_id){
console.log(v);
return products[k]; //returns from the $.each callback
}
});
return false;
}
No need for jQuery's each function. Use libraries only when they are needed.
The problem is, that the 'each' method, is in fact ANOTHER function. Returning from it means nothing to the 'findProduct' function.
function findProduct(product_id){
for(var k in products){
var product = products[k];
if(product && product.Product && product.Product.id == product_id)
return product;
}
return false;
}
Related
In the following code, the function findById() does not actually return anything. The console.log()s fire and print as expected but the result is that the variable the function is being called to is undefined.
I have tried to change return value types, even simply putting return true; at the end with no conditional, but it always is undefined. To make sure I was not missing something simple I actually created a function that only returns a value istrue(). This actually works fine.
This is the object/method def
const database = {
// List of authenticated characters
characters: [],
addCharacter: function(c) {
this.characters.push(c);
},
findById: function(id) {
console.log('Searching for character...');
this.characters.forEach((c) => {
if (c.id === id) {
console.log('Found');
console.log('cid: ' + c.id);
console.log('id: ' + id);
return true; // Never actually returns
}
});
},
istrue: function() {
return true;
}
};
and where it is being called
const find = database.findById(characterIdToFind);
console.log(typeof find); // always undefined
console.log(find); // always undefined
I expect there to be some kind of return value in at least one of the permutations of this function I have tried. There is never any change in the return value of the function, simply undefined.
The return statement inside a nested function return from function.
In this case you could use some() instead of forEach() because you can't break forEach.
findById: function(id) {
console.log('Searching for character...');
return this.characters.some(c => c.id === id)
}
If you want to get the object which matches the given condition that use find()
findById: function(id) {
console.log('Searching for character...');
return this.characters.find(c => c.id === id)
}
If you see in above both method we are returning c.id === id implicitly in each iteration but it doesn't return from outer function.
This is because you are trying to return from forEach & forEach does not return anything
This function is only returning true. I have added a console.log in the if block and it is called but the function doesn't return false.
function isUniform(List)
{
var ele = List[0];
List.forEach(function(item)
{
console.log(ele);
if(ele !== item)
{
return false;
}
})
return true;
}
You need another method for testing unifomity. Better use Array#every, which checks every value with the first item of the array and return true, if all elements are equal and false if not. The iteration stops with the first unequal element.
function isUniform(list) {
return list.every(function(item, _, array) {
return item === array[0];
});
}
The used Array#forEach returns always undefined:
forEach() executes the callback function once for each array element; unlike map() or reduce() it always returns the value undefined and is not chainable.
I think you can use this code;
function isUniform(List)
{
var res = true;
var ele = List[0];
List.forEach(function(item)
{
console.log(ele);
if(ele !== item)
{
res = false;
return;
}
})
return res;
}
This is my code
function nameIsDuplicate(name){
objects = $("#content").find('p.itemOldName');
$(objects).each(function(i, object){
console.log("*"+($(object).text()).toLowerCase() + "*" + name.toLowerCase()+"*");
if(($(object).text()).toLowerCase() == name.toLowerCase())
return true;
});
return false;
}
I am building an online file manager system.
the name argument is a name provided by the user via a textbox, and the $(object).text() is the name of files and folders in the current directory. These names come via exec("ls") command.
I need to check if the name provided by the user already exists. So I compare the name with every files/folders name. The problem is it doesn't find duplicates. The result of the above code is given in the following image
The return true returns out of the each callback. That has no effect on each (it only cares about return false) and doesn't do anything to set the return value of nameIsDuplicate.
You want to return false there (no need to keep looking) and set a flag so your nameIsDuplicate can return it:
function nameIsDuplicate(name){
var duplicate = false;
objects = $("#content").find('p.itemOldName');
$(objects).each(function(i, object){
console.log("*"+($(object).text()).toLowerCase() + "*" + name.toLowerCase()+"*");
if(($(object).text()).toLowerCase() == name.toLowerCase()) {
duplicate = true;
return false; // Stop looping
}
});
return duplicate;
}
However, that function can be a lot simpler using Array.prototype.some:
function nameIsDuplicate(name){
var objects = $("#content").find('p.itemOldName');
name = name.toLowerCase();
return objects.get().some(function(object) {
return $(object).text().toLowerCase() === name;
});
}
some calls its callback for each entry in the array. If the callback returns a falsy value, some keeps going; if the callback returns a truthy value, some stops. some's return value is true if a call to the callback returned a truthy value, false if not.
Your function doesn't return true, because you are in each loop... should be something like this:
function nameIsDuplicate(name){
var same=0;
objects = $("#content").find('p.itemOldName');
$(objects).each(function(i, object){
console.log("*"+($(object).text()).toLowerCase() + "*" + name.toLowerCase()+"*");
if(($(object).text()).toLowerCase() == name.toLowerCase()){
same=1;
return false;
}
});
if(same){
return true;
}else{
return false;
}
}
We can break the $.each() loop at a particular iteration by making the
callback function return false. Returning non-false is the same as a
continue statement in a for loop; it will skip immediately to the next
iteration.
Other solution:
function nameIsDuplicate(name){
return $("#content").find('p.itemOldName').filter(function(){return $(this).text().toLowerCase() === name.toLowerCase();}).length;
}
Jquery function is returning true and false. I think the problem might rise from my each loop.
function myfunction(param){
$.each(param, function(i, item){
if(condition) return false;
});
}
$.when(myfunction(param)).then(function(){
console.log('true');
}, function(){
console.log('false');
});
This then my function returns true and false so i could not resolve when.
How to make the function to return false on condition.
My actual code
function checkName(nameValue){
var currlist = $( ".sortable-fields."+formType).find('li.sortable-field');
var result = true;
$.each(currlist, function(i, item){
var elem = $(item);
var data = elem.data('fieldData');
if(data['name'] == nameValue) {
result = false;
return false;
}
});
return result;
}
Returning within the each callback has a different connotation than returning a result from a function. Use a variable to return after the each is done iterating
function myfunction(param){
var result = true;
$.each(param, function(i, item){
if(condition){
result = false;
return false;
}
});
return result;
}
Returning false within each itself just signals a stop to the iterations.
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
}
}