1

I'm attempting to compare two arrays using the jQuery's .inArray. This seems straightforward but each value that is compared comes back as -1 (not in the array). Below is my code

finalClick();
function finalClick(){
    roles=["President", "Dog", "Treasurer"]
    neededRoles=["President", "Secretary", "Treasurer"];
    $(neededRoles).each(function(){
        if(jQuery.inArray(this, roles)=='-1'){
            console.log("not in array "+this);
        }
    });
}

If you want to play around with it, you can check out my fiddle here.

Thanks in advance

3
  • @Bergi Strict mode can be avoided in favour of modern methods: neededRoles.forEach(role) { if( roles.indexOf(role) < 0) console.log("Not in array: "+role); } ;) Commented Jun 19, 2015 at 8:51
  • @NiettheDarkAbsol: It can, but strict mode is a Good Thing(tm). :-) Commented Jun 19, 2015 at 9:00
  • @NiettheDarkAbsol: Wait, you dare not to use jQuery at all?! :-) Commented Jun 19, 2015 at 9:14

2 Answers 2

6

In loose mode, this is always an object type, not a primitive type. So the this in your callback is a String, not a primitive string. inArray uses === (strict equality) for the check, and a primitive string is not strictly equal to a String object.

Several options for you:

Use strict mode

In strict mode, this can be a primitive, and so your code works (if I add variable declarations; see the "side note" at the end of the answer):

"use strict";
var consoleLine = "<p class=\"console-line\"></p>";
console = {
    log: function (text) {
        $("#console-log").append($(consoleLine).html(text));
    }
};
finalClick();
function finalClick(){
    var roles=["President", "Dog", "Treasurer"]
    var neededRoles=["President", "Secretary", "Treasurer"];
    // console.log("test: "+roles[0]);
    var rolecount=0;
    console.log("value changed");
    $(neededRoles).each(function(){
        //console.log("this is this "+this+" "+rolecount+" "+roles[rolecount]);
        if(jQuery.inArray(this, roles)=='-1'){
            console.log("Not in array "+this);
        } else {
            console.log("Found in array "+this);
        }
        //rolecount++;
    });
}
<div id="console-log"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Use $.each instead of $().each

Instead of $(neededRoles).each(...), use $.each(neededRoles, function(index, role) and use role, which will be a string primitive:

var consoleLine = "<p class=\"console-line\"></p>";
var console = {
    log: function (text) {
        $("#console-log").append($(consoleLine).html(text));
    }
};
finalClick();
function finalClick(){
    var roles=["President", "Dog", "Treasurer"]
    var neededRoles=["President", "Secretary", "Treasurer"];
    // console.log("test: "+roles[0]);
    var rolecount=0;
    console.log("value changed");
    $.each(neededRoles, function(index, role){
        //console.log("this is this "+this+" "+rolecount+" "+roles[rolecount]);
        if(jQuery.inArray(role, roles) == -1){
            console.log("Not in array " + role);
        } else {
            console.log("Found in array " + role);
        }
        //rolecount++;
    });
}
<div id="console-log"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Use Array#forEach and Array#indexOf

Or better yet, use Array#forEach and Array#indexOf, shimming them on really old browsers that don't have them:

var consoleLine = "<p class=\"console-line\"></p>";
var console = {
    log: function (text) {
        $("#console-log").append($(consoleLine).html(text));
    }
};
finalClick();
function finalClick(){
    var roles=["President", "Dog", "Treasurer"]
    var neededRoles=["President", "Secretary", "Treasurer"];
    // console.log("test: "+roles[0]);
    var rolecount=0;
    console.log("value changed");
    neededRoles.forEach(function(role) {
        if (roles.indexOf(role) == -1) {
            console.log("Not in array " + role);
        } else {
            console.log("Found in array " + role);
        }
        //rolecount++;
    });
}
<div id="console-log"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Use Array#filter

If your goal is to find missing roles that are required, you can use Array#filter:

var consoleLine = "<p class=\"console-line\"></p>";
var console = {
  log: function(text) {
    $("#console-log").append($(consoleLine).html(text));
  }
};
finalClick();

function finalClick() {
  var roles = ["President", "Dog", "Treasurer"]
  var neededRoles = ["President", "Secretary", "Treasurer"];
  var missingRoles = neededRoles.filter(function(role) {
    return roles.indexOf(role) == -1;
  });
  console.log("Missing roles: " + missingRoles.join(", "));
}
<div id="console-log"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>


Side note: Your original code was falling prey to The Horror of Implicit Globals because you weren't declaring a lot of your variables. I've fixed that in all of the above examples.

Sign up to request clarification or add additional context in comments.

4 Comments

+1 for the thorough explanation - the difference between primitives and wrapper objects is easily forgotten.
You could also just change this to this.toString()? jsfiddle.net/ctn2zv5n
@JamieBarker: Hah! Yes, you could. :-)
@JamieBarker Or ""+this but do you really want to throw another "hack" into the mix?
3

The jQuery each method has 2 parameters: index and element. If you use these parameters instead of this your code works

var consoleLine = "<p class=\"console-line\"></p>";
console = {
    log: function (text) {
        $("#console-log").append($(consoleLine).html(text));
    }
};
finalClick();

function finalClick() {
    roles = ["President", "Dog", "Treasurer"]
    neededRoles = ["President", "Secretary", "Treasurer"];
    // console.log("test: "+roles[0]);
    rolecount = 0;
    console.log("value changed");
    $(neededRoles).each(function (i, e) {        // using index and element
        if (jQuery.inArray(e, roles) == '-1') {
            console.log("not in array " + e);
        }
    });
}

jQuery doc for each method

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy 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.