0

i'm trying to create a function that take an array as an argument, and return "true" only if all the items inside the array are the same .
i try to usefor loop and i try to useforEeach loop
the first one work great.
the second one not!.
why?
this my first code:

function isUniform(ary) {    var first = ary[0];    for (i = 0; i < ary.length; i++) {        if (first !== ary[i]) {            return false;        }    }        return true;}console.log(isUniform([1, 2, 1]));

this my second one:

function isUniform(ary) {    var first = ary[0];    ary.forEach(function(element) {        if (first !== element) {            return false;        }    });    return true;} console.log(isUniform([1, 2, 1]));
askedJun 24, 2017 at 23:38
Nave Hazan's user avatar
2
  • How about logging the values in the forEach loop and checking what they are?CommentedJun 24, 2017 at 23:45
  • @ChrisSatchell that's irrelevant ... the issue is there is nowhere to return to inforEach and return of an inner closure doesn't return to the outer oneCommentedJun 24, 2017 at 23:46

5 Answers5

7

The "inner"return in your second example is a return from the function passed toforEach. It doesnot cause an immediate return from theisUniform function. Instead, this little anonymous function you passed toforEach runs happily to completion for every single element of your array.

After it finishes running through all of the elements, yourisUniform function then simply returns true.

answeredJun 24, 2017 at 23:43
Ray Toal's user avatar
Sign up to request clarification or add additional context in comments.

Comments

1

By returning true you are returning true to the forEach function callback while you're for loop returns true to the function. Your forEach requires a reference object when executing a callback if you want to use your current approach. That is how it is different from your for loop.

function isUniform(ary) {  var first = ary[0];  val = true;  ary.forEach(element => {    if (first !== element) {      val = false;    }  });  return val;}console.log(isUniform([1, 1, 1]));console.log(isUniform([1, 2, 1]));

There is already an every function you can take advantage of.

arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];arr2 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];console.log(arr1.every((a, _, aa) => aa[0] === a));console.log(arr2.every((a, _, aa) => aa[0] === a));

answeredJun 24, 2017 at 23:44
Rick's user avatar

6 Comments

While true this doesn't answer the question. Why is forEach different?
With thatval you should really stick to the lexical closure, just as you do withfirst. Bringingthis into the picture pollutes the context and also makes the code confusing to read.
@Amy because of design/definition.forEach is not a conditional construct, and it does not care/check/forward/store/accumulate/etc. whatever the called function returns. If one really wants to break from aforEach loop, throwing an exception can do that, but it is not a nice solution.
Actually Amy wasn't really asking a question here, but rather pointing out, via a rhetorical device, that the answer here simply gave a forEach-based solution to a piece of code while the OP specifically asked "WHY does the forEach code fail while the for-loop code succeeds?" Cheers.
@tevemadar I know this. I was prompting him to actually answer the question.
|
0

You can't break from a forEach.

Try this one. You can do it with the flag.

var falg = false;

function isUniform(ary) {

var first = ary[0];ary.forEach(function(element) {    if (first !== element) {        falg = true;        return false;    }});if(falg)    return falsereturn true;

}

console.log(isUniform([1, 2, 1]));

answeredJun 25, 2017 at 0:02
Prakash Sundar's user avatar

Comments

0

The how part has been addressed in @Arrow's post already, if you work withforEach, it does not care about the return values, you have to accumulate the result yourself (also, there is no 'normal' way of breaking out from the loop, though you could throw an exception if you really want to).

For the 'why' part: because of definition.forEach does not care about return values and runs the passed function for all elements, unconditionally.

A simplified implementation offorEach is the following:

Array.prototype.myForEach=function(callback){ // or callback,diz  for(var i=0;i<this.length;t++)    callback(this[i],i,this);                 // or callback.call(diz,this[i],i,this);}

The result ofcallback is completely ignored. (Commented parts add support for the optional context-argument)

A 'more official' polyfill does some extra checks, but it is not complicated either:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#Polyfill

answeredJun 26, 2017 at 12:43
tevemadar's user avatar

Comments

-1

can you try this, change the var element for x, and use lambdas

    function isUniform(ary) {     var first = ary[0];     ary.forEach((x) => {         if(first !== x){             return false;         }     });     return true;    }
answeredJun 24, 2017 at 23:48
Adrià Cabezuelo's user avatar

Comments

Your Answer

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.