true

What is the most concise and efficient way to find out if a JavaScript array contains an object?

This is the only way I know to do it:

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (a[i] === obj) {
            return true;
        }
    }
    return false;
}

Is there a better and more concise way to accomplish this?

This is very closely related to Stack Overflow question Best way to find an item in a JavaScript Array? which addresses finding objects in an array using indexOf.

34 upvote
  flag
just tested: your way is actually the fastest for across browsers: jsperf.com/find-element-in-obj-vs-array/2 (apart from pre-saving a.length in a variable) while using indexOf (as in $.inArray) is much slower – Jörn Berkefeld
13 upvote
  flag
many have replied that the Array#indexOf is your best choice here. But if you want something that can be correctly cast to Boolean, use this: ~[1,2,3].indexOf(4) will return 0 which will evaluate as false, whereas ~[1,2,3].indexOf(3) will return -3 which will evaluate as true. – lordvlad
5 upvote
  flag
~ is not what you want to use to convert to a boolean, for that you need !. But in this case you want to check equality with -1, s o the function might endreturn [1,2,3].indexOf(3) === -1; ~ is a binary not, it will invert each bit of the value individually. – mcfedr
upvote
  flag
IE9 supports indexOf() as per w3schools.com/jsref/jsref_indexof_array.asp. If older browser better approach is to define prototype for indexOf() function as given in Array.indexOf in Internet Explorer – Lijo
8 upvote
  flag
@Iordvlad [1,2,3].indexOf(4) will actually return -1. As @mcfedr pointed out, ~ is the bitwise-NOT operator, see ES5 11.4.8. Thing is, since the binary representation of -1 consists of only 1's, it's complement is 0, which evaluates as false. The complement of any other number will be non-zero, hence true. So, ~ works just fine and is often used in conjunction with indexOf. – mknecht
upvote
  flag
The title is misleading. Where is the [[1,2],[3,4]].includes([3,4]) ? – mplungjan

39 Answers 11

If you are using JavaScript 1.6 or later (Firefox 1.5 or later) you can use Array.indexOf. Otherwise, I think you are going to end up with something similar to your original code.

indexOf maybe, but it's a "JavaScript extension to the ECMA-262 standard; as such it may not be present in other implementations of the standard."

Example:

[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1

AFAICS Microsoft does not offer some kind of alternative to this, but you can add similar functionality to arrays in Internet Explorer (and other browsers that don't support indexOf) if you want to, as a quick Google search reveals (for example, this one).

upvote
  flag
actually, there is an example of the an implementation of the indexOf extension for browsers that do not support it on the developer.mozilla.org page you linked to. – Lloyd Cotten
upvote
  flag
actually, if you add indexof to the prototype of Array for browsers that don't support it (i.e. IE7) they will also try to loop over this function when looping through the items in the array. nasty. – CpILL
3 upvote
  flag

Update: As @orip mentions in comments, the linked benchmark was done in 2008, so results may not be relevant for modern browsers. However, you probably need this to support non-modern browsers anyway and they probably haven't been updated since. Always test for yourself.

As others have said, the iteration through the array is probably the best way, but it has been proven that a decreasing while loop is the fastest way to iterate in JavaScript. So you may want to rewrite your code as follows:

function contains(a, obj) {
    var i = a.length;
    while (i--) {
       if (a[i] === obj) {
           return true;
       }
    }
    return false;
}

Of course, you may as well extend Array prototype:

Array.prototype.contains = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
}

And now you can simply use the following:

alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false
23 upvote
  flag
upvote
  flag
This works fine with Titanium 1.7.2. – neoneye
17 upvote
  flag
"Proven" is a strong word. JS engines constantly improve, and execution time measured 3 years ago is terribly outdated. – orip
upvote
  flag
@orip excellent point. But even so, for the slowest browser out there it's still valid. For the modern browsers the difference is either negligible or irrelevant (since they already support indexOf). I've updated the answer, thanks. – Damir Zekić
2 upvote
  flag
@Damir - I agree. Perhaps change the sample to use indexOf if available, just so people copy-pasting this code blindly will get the best performance they can. – orip
upvote
  flag
extending the Array like this will cause one more issue. if you use for(x in myArray) it will cycle through the prototype methods too, so you need to check if each x is a property now. I'm looking right now to see if there is a way to remedy this without having to redo all my for(in). – Chris Stephens
upvote
  flag
you should use i in obj && ... === ... because in case of sparse arrays var arr=[];arr[4]="d"; it will wrongly return true when searching for undefined – ajax333221
upvote
  flag
+1 for giving the LINK to the proof of iteration times... eye-opening revelations in relation to looping over HTML elements... – kumar_harsh
1 upvote
  flag
@cbmeeks yeah, care is definitely needed. It was probably a case of doing for (o in array) which shouldn't be done when looping through the array generally... – Damir Zekić
1 upvote
  flag
The best way to do this is check if [1, 2, 3].indexOf(1) > -1 – Devin G Rhode
upvote
  flag
Does your contains function works in all old and new browser? – Thomas
upvote
  flag
@Thomas yes, it should work in all browsers. – Damir Zekić
upvote
  flag
what prototype() does in js? does it use to add any extension to any class or object from out side? – Thomas
upvote
  flag
In nodejs (v7.4.0) on my windows 7 64 bit machine, looking up for a 1 in an array with 10M zeros; the "while" loop takes about 240+ ms, "for" loop (also counting down) takes about 220 ms and "indexOf" method takes about 20 ms. If I fill up that array with some incrementing numbers (0 to 10M-1) and look for -1, while loop becomes faster about 4 times, for loop becomes faster about 8 times and indexOf takes about 25-50% more time. Color me surprised. – mkey

Here's a JavaScript 1.6 compatible implementation of Array.indexOf:

if (!Array.indexOf)
{
  Array.indexOf = [].indexOf ?
      function (arr, obj, from) { return arr.indexOf(obj, from); }:
      function (arr, obj, from) { // (for IE6)
        var l = arr.length,
            i = from ? parseInt( (1*from) + (from<0 ? l:0), 10) : 0;
        i = i<0 ? 0 : i;
        for (; i<l; i++) {
          if (i in arr  &&  arr[i] === obj) { return i; }
        }
        return -1;
      };
}
upvote
  flag
This looks great, but a little confused: * Aren't the tests on lines 1 and 3 equivalent? * Wouldn't it be better to test the prototype, and add the function to Array.prototype if necessary? – Avi Flax
9 upvote
  flag
They aren't equvialent. [].indexOf is a shorthand for Array.prototype.indexOf. Us paranoid-defensive Javascript programmers avoid extending native prototypes at all cost. – Már Örlygsson
1 upvote
  flag
Isn't [].indexOf creating a new array and then accessing indexOf, whilst Array.prototype.indexOf just accesses the prototype directly? – alex
3 upvote
  flag
@alex yes [].indexOf === Array.prototype.indexOf (try it out in FireBug), but conversely [].indexOf !== Array.indexOf. – Már Örlygsson

Extending the JavaScript Array object is a really bad idea because you introduce new properties (your custom methods) into for-in loops which can break existing scripts. A few years ago the authors of the Prototype library had to re-engineer their library implementation to remove just this kind of thing.

If you don't need to worry about compatibility with other JavaScript running on your page, go for it, otherwise, I'd recommend the more awkward, but safer free-standing function solution.

22 upvote
  flag
I disagree. For-in loops should not be used for arrays for precisely this reason. Using for-in loops will break when using one of the popular js libraries – Tomas
upvote
  flag
Would this be considered monkey patching? lol Some people like that. – cbmeeks

Here's how Prototype does it:

/**
 *  Array#indexOf(item[, offset = 0]) -> Number
 *  - item (?): A value that may or may not be in the array.
 *  - offset (Number): The number of initial items to skip before beginning the
 *      search.
 *
 *  Returns the position of the first occurrence of `item` within the array &mdash; or
 *  `-1` if `item` doesn't exist in the array.
**/
function indexOf(item, i) {
  i || (i = 0);
  var length = this.length;
  if (i < 0) i = length + i;
  for (; i < length; i++)
    if (this[i] === item) return i;
  return -1;
}

Also see here for how they hook it up.

up vote 3466 down vote accepted

Current browsers have Array#includes, which does exactly that, is widely supported, and has a polyfill for older browsers.

You can also use Array#indexOf, which is less direct, but doesn't require Polyfills for out of date browsers.

jQuery offers $.inArray, which is functionally equivalent to Array#indexOf.

underscore.js, a JavaScript utility library, offers _.contains(list, value), alias _.include(list, value), both of which use indexOf internally if passed a JavaScript array.

Some other frameworks offer similar methods:

Notice that some frameworks implement this as a function, while others add the function to the array prototype.

39 upvote
  flag
MooTools also has Array.contains that returns a boolean, which sounds like the real question here. – Ryan Florence
17 upvote
  flag
prototype also has Array.include that returns a boolean – user102008
40 upvote
  flag
If you are using a good browser, you can just use array.indexOf(object) != -1 – Sam Soffes
upvote
  flag
@user102008: MDN doesn't include any reference to Array.include (MDN Array Reference - I was looking to see what version of JS that was in.) Where did you see a reference to that method? – zcrar70
10 upvote
  flag
Also, dont use indexOf alone as a condition, because the first element will return 0 and will be evaluated as falsy – plus-
209 upvote
  flag
inArray is a terrible name for a function that returns the index of the element, and -1 if it doesn't exist. I would expect a boolean to be returned. – Tim
upvote
  flag
var inArray = function(a,b,c,d){for(c in b)d|=b[c]===a;return!!d } – Om Shankar
upvote
  flag
did underscore remove include? – jcolebrand
upvote
  flag
@jcolebrand I updated the answer. include is still there, but is in the docs listed as an alias for contains – codeape
upvote
  flag
@Tim I guess it returns -1 to negate the chance of 0 being taken as falsey – Relequestual
upvote
  flag
doesn't 2 in [1, 2, 3] work too? – Iulian Onofrei
upvote
  flag
I think someone mentioned that you can get around 0 being evaluated as false by using the === operator, if only in passing. – Aaron Mason
upvote
  flag
I thought dart was it's own language. Does it actually compile to JS? Edit: oh, it can be compiled to JS, though it runs best on a browser made to run it. – slicedtoad
8 upvote
  flag
@IulianOnofrei: No, 2 in [1,2,3] == true, but 5 in [3,4,5] == false. Why? Because arrays in JavaScripts behave just like regular objects, so 2 in array actually only means that array[2] is defined. Mind that this behaviour is still potentially useful, since JavaScript arrays can be sparse: 2 in [1,2,,3] == false – Witiko
upvote
  flag
You should also check this proposal: github.com/tc39/Array.prototype.includes Also this for different ways to use Array.prototype.indexOf(): codereview.stackexchange.com/questions/13941/… – AlicanC
upvote
  flag
Why not provide an example in the answer? if($.inArray(value, array)) > -1 { // found value in array } – Kai Noack
upvote
  flag
now 2016, and i still can't use .include and .indexOf properly on non primitive type. – Adi Prasetyo

Thinking out of the box for a second, if you are in making this call many many times, it is vastly more efficient to use an associative array a Map to do lookups using a hash function.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

Just another option

// usage: if ( ['a','b','c','d'].contains('b') ) { ... }
Array.prototype.contains = function(value){
    for (var key in this)
        if (this[key] === value) return true;
    return false;
}
1 upvote
  flag
20 upvote
  flag
Please don't use a for in loop to iterate over an array - for in loops should be used strictly for objects only. – Yi Jiang

If you are checking repeatedly for existence of an object in an array you should maybe look into

  1. Keeping the array sorted at all times by doing insertion sort in your array (put new objects in on the right place)
  2. Make updating objects as remove+sorted insert operation and
  3. Use a binary search lookup in your contains(a, obj).
2 upvote
  flag
Or if possible, stop using an Array entirely, and instead use an Object as a dictionary, as MattMcKnight and ninjagecko have suggested. – joeytwiddle

Literally:

(using Firefox v3.6, with for-in caveats as previously noted (HOWEVER the use below might endorse for-in for this very purpose! That is, enumerating array elements that ACTUALLY exist via a property index (HOWEVER, in particular, the array length property is NOT enumerated in the for-in property list!).).)

(Drag & drop the following complete URI's for immediate mode browser testing.)

JavaScript:

  function ObjInRA(ra){var has=false; for(i in ra){has=true; break;} return has;}

  function check(ra){
      return ['There is ',ObjInRA(ra)?'an':'NO',' object in [',ra,'].'].join('')
  }
  alert([
            check([{}]), check([]), check([,2,3]),
            check(['']), '\t (a null string)', check([,,,])
        ].join('\n'));

which displays:

There is an object in [[object Object]].
There is NO object in [].
There is an object in [,2,3].
There is an object in [].
     (a null string)
There is NO object in [,,].

Wrinkles: if looking for a "specific" object consider:

JavaScript: alert({}!={}); alert({}!=={});

And thus:

JavaScript:

 obj = {prop:"value"}; 
 ra1 = [obj]; 
 ra2 = [{prop:"value"}];
 alert(ra1[0] == obj); 
 alert(ra2[0] == obj);

Often ra2 is considered to "contain" obj as the literal entity {prop:"value"}.

A very coarse, rudimentary, naive (as in code needs qualification enhancing) solution:

JavaScript:

  obj={prop:"value"};   ra2=[{prop:"value"}];
  alert(
    ra2 . toSource() . indexOf( obj.toSource().match(/^.(.*).$/)[1] ) != -1 ?
      'found' :
      'missing' );

See ref: Searching for objects in JavaScript arrays.

Use:

Array.prototype.contains = function(x){
  var retVal = -1;

  // x is a primitive type
  if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}

  // x is a function
  else if(typeof x =="function") for(var ix in this){
    if((this[ix]+"")==(x+"")) retVal = ix;
  }

  //x is an object...
  else {
    var sx=JSON.stringify(x);
    for(var ix in this){
      if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
    }
  }

  //Return False if -1 else number if numeric otherwise string
  return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
}

I know it's not the best way to go, but since there is no native IComparable way to interact between objects, I guess this is as close as you can get to compare two entities in an array. Also, extending Array object might not be a wise thing to do, but sometimes it's OK (if you are aware of it and the trade-off).

b is the value, and a is the array. It returns true or false:

function(a, b) {
    return a.indexOf(b) != -1
}
upvote
  flag
It returns true if "b" is in the array "a"... I don't know how else to explain it... – william malo
4 upvote
  flag
This part I dont understand "!!~". And I think this will not work in IE8 because IE8 doesnt support indexOf() on Array object. – svlada
60 upvote
  flag
"~" is an operator that floors, inverts and subtracts 1 from a number. indexOf returns -1 if it fails, so "~" turns -1 into "0". using "!!" turns numbers into boleans (!!0===false) – william malo
15 upvote
  flag
the same performance as !=-1 jsperf.com/indexof-check – aelgoa
1 upvote
  flag
Cool, but seriously for the sake of simplicity y not just a.indexOf(b)>-1, since ">-1".length === "!!~".length – super
4 upvote
  flag
Just a bit of throw-up, right in my mouth. Absolutely unprofessional code. – Michael Cole
2 upvote
  flag
I'd call the lack of knowledge about the effects of boolean operators unprofessional. But I agree about the value of readable code, I would certainly wrap this in a clearly labelled function. And that's exactly what most major JS frameworks do. – Fx32

While array.indexOf(x)!=-1 is the most concise way to do this (and has been supported by non-Internet Explorer browsers for over decade...), it is not O(1), but rather O(N), which is terrible. If your array will not be changing, you can convert your array to a hashtable, then do table[x]!==undefined or ===undefined:

Array.prototype.toTable = function() {
    var t = {};
    this.forEach(function(x){t[x]=true});
    return t;
}

Demo:

var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})

(Unfortunately, while you can create an Array.prototype.contains to "freeze" an array and store a hashtable in this._cache in two lines, this would give wrong results if you chose to edit your array later. JavaScript has insufficient hooks to let you keep this state, unlike Python for example.)

function inArray(elem,array)
{
    var len = array.length;
    for(var i = 0 ; i < len;i++)
    {
        if(array[i] == elem){return i;}
    }
    return -1;
} 

Returns array index if found, or -1 if not found

Similar thing: Finds the first element by a "search lambda":

Array.prototype.find = function(search_lambda) {
  return this[this.map(search_lambda).indexOf(true)];
};

Usage:

[1,3,4,5,8,3,5].find(function(item) { return item % 2 == 0 })
=> 4

Same in coffeescript:

Array.prototype.find = (search_lambda) -> @[@map(search_lambda).indexOf(true)]
upvote
  flag
This certainly is much more flexible than many of the other approaches. If one is uncomfortable with the prototype one might consider something like var positionIf = function (predicate,sequence) {return sequence.map(predicate).indexOf(true);}; – dat
2 upvote
  flag
A more efficient way to implement this method would be to use a loop and stop applying search_lambda once something is found. – Casey Chu

As others have mentioned you can use Array.indexOf, but it isn't available in all browsers. Here's the code from https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf to make it work the same in older browsers.

indexOf is a recent addition to the ECMA-262 standard; as such it may not be present in all browsers. You can work around this by inserting the following code at the beginning of your scripts, allowing use of indexOf in implementations which do not natively support it. This algorithm is exactly the one specified in ECMA-262, 5th edition, assuming Object, TypeError, Number, Math.floor, Math.abs, and Math.max have their original value.

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
        "use strict";
        if (this == null) {
            throw new TypeError();
        }
        var t = Object(this);
        var len = t.length >>> 0;
        if (len === 0) {
            return -1;
        }
        var n = 0;
        if (arguments.length > 1) {
            n = Number(arguments[1]);
            if (n != n) { // shortcut for verifying if it's NaN
                n = 0;
            } else if (n != 0 && n != Infinity && n != -Infinity) {
                n = (n > 0 || -1) * Math.floor(Math.abs(n));
            }
        }
        if (n >= len) {
            return -1;
        }
        var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
        for (; k < len; k++) {
            if (k in t && t[k] === searchElement) {
                return k;
            }
        }
        return -1;
    }
}

I looked through submitted answers and got that they only apply if you search for the object via reference. A simple linear search with reference object comparison.

But lets say you don't have the reference to an object, how will you find the correct object in the array? You will have to go linearly and deep compare with each object. Imagine if the list is too large, and the objects in it are very big containing big pieces of text. The performance drops drastically with the number and size of the elements in the array.

You can stringify objects and put them in the native hash table, but then you will have data redundancy remembering these keys cause JavaScript keeps them for 'for i in obj', and you only want to check if the object exists or not, that is, you have the key.

I thought about this for some time constructing a JSON Schema validator, and I devised a simple wrapper for the native hash table, similar to the sole hash table implementation, with some optimization exceptions which I left to the native hash table to deal with. It only needs performance benchmarking... All the details and code can be found on my blog: http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/ I will soon post benchmark results.

The complete solution works like this:

var a = {'a':1,
 'b':{'c':[1,2,[3,45],4,5],
 'd':{'q':1, 'b':{'q':1, 'b':8},'c':4},
 'u':'lol'},
 'e':2};

 var b = {'a':1, 
 'b':{'c':[2,3,[1]],
 'd':{'q':3,'b':{'b':3}}},
 'e':2};

 var c = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";

 var hc = new HashCache([{a:3, b:2, c:5}, {a:15, b:2, c:'foo'}]); //init

 hc.put({a:1, b:1});
 hc.put({b:1, a:1});
 hc.put(true);
 hc.put('true');
 hc.put(a);
 hc.put(c);
 hc.put(d);
 console.log(hc.exists('true'));
 console.log(hc.exists(a));
 console.log(hc.exists(c));
 console.log(hc.exists({b:1, a:1}));
 hc.remove(a);
 console.log(hc.exists(c));

Use:

function isInArray(array, search)
{
    return array.indexOf(search) >= 0;
}

// Usage
if(isInArray(my_array, "my_value"))
{
    //...
}
25 upvote
  flag
x ? true : false is usually redundant. It is here. – Ryan
upvote
  flag
@minitech Why do you say it is redundant? – Matías Cánepa
8 upvote
  flag
array.indexOf(search) >= 0 is already a boolean. Just return array.indexOf(search) >= 0. – Ryan
upvote
  flag
@minitech well thanks! Actually I didn't know that such a construction could be returned. TIL something new. – Matías Cánepa
upvote
  flag
Literally any construct in javascript can be returned – B T

Use:

var myArray = ['yellow', 'orange', 'red'] ;

alert(!!~myArray.indexOf('red')); //true

Demo

To know exactly what the tilde ~ do at this point, refer to this question What does a tilde do when it precedes an expression?.

4 upvote
  flag
This was already posted year and half ago no need to repeat it. – Shadow Wizard

ECMAScript 6 has an elegant proposal on find.

The find method executes the callback function once for each element present in the array until it finds one where callback returns a true value. If such an element is found, find immediately returns the value of that element. Otherwise, find returns undefined. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.

Here is the MDN documentation on that.

The find functionality works like this.

function isPrime(element, index, array) {
    var start = 2;
    while (start <= Math.sqrt(element)) {
        if (element % start++ < 1) return false;
    }
    return (element > 1);
}

console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5

You can use this in ECMAScript 5 and below by defining the function.

if (!Array.prototype.find) {
  Object.defineProperty(Array.prototype, 'find', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(predicate) {
      if (this == null) {
        throw new TypeError('Array.prototype.find called on null or undefined');
      }
      if (typeof predicate !== 'function') {
        throw new TypeError('predicate must be a function');
      }
      var list = Object(this);
      var length = list.length >>> 0;
      var thisArg = arguments[1];
      var value;

      for (var i = 0; i < length; i++) {
        if (i in list) {
          value = list[i];
          if (predicate.call(thisArg, value, i, list)) {
            return value;
          }
        }
      }
      return undefined;
    }
  });
}

I use the following:

Array.prototype.contains = function (v) {
    return this.indexOf(v) > -1;
}

var a = [ 'foo', 'bar' ];

a.contains('foo'); // true
a.contains('fox'); // false

You can use Array.prototype.some()

const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]

items.some(item => item.a === '3')  // returns true
items.some(item => item.a === '4')  // returns false

Upside to this is that the iteration is aborted once the element is found so unnecessary iteration cycles are saved.

One thing to note is that some() is not present in all js versions: (from the website)

some was added to the ECMA-262 standard in the 5th edition; as such it may not be present in all implementations of the standard

You can use it in Node.js without any issue. If you need to support all browsers then there's this polyfill (from the same link):

if (!Array.prototype.some)
{
  Array.prototype.some = function(fun /*, thisArg */)
  {
    'use strict';

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== 'function')
      throw new TypeError();

    var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
    for (var i = 0; i < len; i++)
    {
      if (i in t && fun.call(thisArg, t[i], i, t))
        return true;
    }

    return false;
  };
}

We use this snippet (works with objects, arrays, strings):

/*
 * @function
 * @name Object.prototype.inArray
 * @description Extend Object prototype within inArray function
 *
 * @param {mix}    needle       - Search-able needle
 * @param {bool}   searchInKey  - Search needle in keys?
 *
 */
Object.defineProperty(Object.prototype, 'inArray',{
    value: function(needle, searchInKey){

        var object = this;

        if( Object.prototype.toString.call(needle) === '[object Object]' || 
            Object.prototype.toString.call(needle) === '[object Array]'){
            needle = JSON.stringify(needle);
        }

        return Object.keys(object).some(function(key){

            var value = object[key];

            if( Object.prototype.toString.call(value) === '[object Object]' || 
                Object.prototype.toString.call(value) === '[object Array]'){
                value = JSON.stringify(value);
            }

            if(searchInKey){
                if(value === needle || key === needle){
                return true;
                }
            }else{
                if(value === needle){
                    return true;
                }
            }
        });
    },
    writable: true,
    configurable: true,
    enumerable: false
});

Usage:

var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first");          //true
a.inArray("foo");            //false
a.inArray("foo", true);      //true - search by keys
a.inArray({three: "third"}); //true

var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one");         //true
b.inArray('foo');         //false
b.inArray({foo: 'val'})   //true
b.inArray("{foo: 'val'}") //false

var c = "String";
c.inArray("S");        //true
c.inArray("s");        //false
c.inArray("2", true);  //true
c.inArray("20", true); //false
upvote
  flag
I'll just leave it here JS-inArray – dr.dimitru
function contains(a, obj) {
    return a.some(function(element){return element == obj;})
}

Array.prototype.some() was added to the ECMA-262 standard in the 5th edition

ECMAScript 7 introduces Array.prototype.includes.

It can be used like this:

[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false

It also accepts an optional second argument fromIndex:

[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true

Unlike indexOf, which uses Strict Equality Comparison, includes compares using SameValueZero equality algorithm. That means that you can detect if an array includes a NaN:

[1, 2, NaN].includes(NaN); // true

Also unlike indexOf, includes does not skip missing indices:

new Array(5).includes(undefined); // true

Currently it's still a draft but can be polyfilled to make it work on all browsers.

3 upvote
  flag
Not supported for IE and Microsfot Edge (2015) (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…‌​) – Adriano Resende
1 upvote
  flag
Also relevant, the ES7 compatibility table (looks like chrome supports it now) – styfle
upvote
  flag
Worth noting that this is supported in Node 6+, according to node.green – Ryan

One-liner:

function contains(arr, x) {
    return arr.filter(function(elem) { return elem == x }).length > 0;
}
2 upvote
  flag
array.filter(e=>e==x).length > 0 is equivalent to array.some(e=>e==x) but some is more efficient – Apolo

A hopefully faster bidirectional indexOf / lastIndexOf alternative

2015

While the new method includes is very nice, the support is basically zero for now.

It's long time that I was thinking of way to replace the slow indexOf/lastIndexOf functions.

A performant way has already been found, looking at the top answers. From those I chose the contains function posted by @Damir Zekic which should be the fastest one. But it also states that the benchmarks are from 2008 and so are outdated.

I also prefer while over for, but for not a specific reason I ended writing the function with a for loop. It could be also done with a while --.

I was curious if the iteration was much slower if I check both sides of the array while doing it. Apparently no, and so this function is around two times faster than the top voted ones. Obviously it's also faster than the native one. This in a real world environment, where you never know if the value you are searching is at the beginning or at the end of the array.

When you know you just pushed an array with a value, using lastIndexOf remains probably the best solution, but if you have to travel through big arrays and the result could be everywhere, this could be a solid solution to make things faster.

Bidirectional indexOf/lastIndexOf

function bidirectionalIndexOf(a, b, c, d, e){
  for(c=a.length,d=c*1; c--; ){
    if(a[c]==b) return c; //or this[c]===b
    if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
  }
  return -1
}

//Usage
bidirectionalIndexOf(array,'value');

Performance test

http://jsperf.com/bidirectionalindexof

As test I created an array with 100k entries.

Three queries: at the beginning, in the middle & at the end of the array.

I hope you also find this interesting and test the performance.

Note: As you can see I slightly modified the contains function to reflect the indexOf & lastIndexOf output (so basically true with the index and false with -1). That shouldn't harm it.

The array prototype variant

Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
  for(c=this.length,d=c*1; c--; ){
    if(this[c]==b) return c; //or this[c]===b
    if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
  }
  return -1
},writable:false, enumerable:false});

// Usage
array.bidirectionalIndexOf('value');

The function can also be easily modified to return true or false or even the object, string or whatever it is.

And here is the while variant:

function bidirectionalIndexOf(a, b, c, d){
  c=a.length; d=c-1;
  while(c--){
    if(b===a[c]) return c;
    if(b===a[d-c]) return d-c;
  }
  return c
}

// Usage
bidirectionalIndexOf(array,'value');

How is this possible?

I think that the simple calculation to get the reflected index in an array is so simple that it's two times faster than doing an actual loop iteration.

Here is a complex example doing three checks per iteration, but this is only possible with a longer calculation which causes the slowdown of the code.

http://jsperf.com/bidirectionalindexof/2

Use lodash's some function.

It's concise, accurate and has great cross platform support.

The accepted answer does not even meet the requirements.

Requirements: Recommend most concise and efficient way to find out if a JavaScript array contains an object.

Accepted Answer:

$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1

My recommendation:

_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true

Notes:

$.inArray works fine for determining whether a scalar value exists in an array of scalars...

$.inArray(2, [1,2])
> 1

... but the question clearly asks for an efficient way to determine if an object is contained in an array.

In order to handle both scalars and objects, you could do this:

(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)

One can use Set that has the method "has()":

function contains(arr, obj) {
  var proxy = new Set(arr);
  if (proxy.has(obj))
    return true;
  else
    return false;
}

var arr = ['Happy', 'New', 'Year'];
console.log(contains(arr, 'Happy'));
1 upvote
  flag
I think return proxy.has(obj) is much cleaner than two lines with if-else statement here – Maciej Bukowski

By no means the best, but I was just getting creative and adding to the repertoire.

Do not use this

Object.defineProperty(Array.prototype, 'exists', {
  value: function(element, index) {

    var index = index || 0

    return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
  }
})


// Outputs 1
console.log(['one', 'two'].exists('two'));

// Outputs -1
console.log(['one', 'two'].exists('three'));

console.log(['one', 'two', 'three', 'four'].exists('four'));

upvote
  flag
What should you use if not this? – bryc
upvote
  flag
@bryc maybe the accepted solution, or another solution from here. If you don't care much for performance, than you can use this – sqram

You can also use this trick:

var arrayContains = function(object) {
  return (serverList.filter(function(currentObject) {
    if (currentObject === object) {
      return currentObject
    }
    else {
      return false;
    }
  }).length > 0) ? true : false
}
upvote
  flag
this seems convoluted. 'object' is a poor name, 'item' might be better. the filter function logic should just be return currentObject === item; and the ternary operator is uncessary.. – TygerKrash

Solution that works in all modern browsers:

function contains(arr, obj) {
  const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
  return arr.some(item => JSON.stringify(item) === stringifiedObj);
}

Usage:

contains([{a: 1}, {a: 2}], {a: 1}); // true

IE6+ solution:

function contains(arr, obj) {
  var stringifiedObj = JSON.stringify(obj)
  return arr.some(function (item) {
    return JSON.stringify(item) === stringifiedObj;
  });
}

// .some polyfill, not needed for IE9+
if (!('some' in Array.prototype)) {
  Array.prototype.some = function (tester, that /*opt*/) {
    for (var i = 0, n = this.length; i < n; i++) {
      if (i in this && tester.call(that, this[i], i, this)) return true;
    } return false;
  };
}

Usage:

contains([{a: 1}, {a: 2}], {a: 1}); // true

Why to use JSON.stringify?

Array.indexOf and Array.includes (as well as most of the answers here) only compare by reference and not by value.

[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object

Bonus

Non-optimized ES6 one-liner:

[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true

Note: Comparing objects by value will work better if the keys are in the same order, so to be safe you might sort the keys first with a package like this one: https://www.npmjs.com/package/sort-keys


Updated the contains function with a perf optimization. Thanks itinance for pointing it out.

upvote
  flag
This particular chunk of code may work in IE6 (haven't tested), but IE didn't support ES5 until IE9. – Mark Reed
upvote
  flag
For performance reasons you should avoid stringifying. At least you should avoid to JSON.stringify the "obj" on every loop because it is expensive and will slow down you application. Therefor you should capture it before the for-loop in a temp variable – itinance
1 upvote
  flag
@itinance good point. Updated the includes function with your suggestion. I've ran jsperf with my function. It's about 5x slower than lodash's includes. Though lodash doesn't compare by value and can't find {a: 1} in [{a: 1}]. I don't know if any library does it. But I'm curious if there's any more performant and not insanely complex way of doing it. – Igor Barbashin

Or this solution:

Array.prototype.includes = function (object) {
  return !!+~this.indexOf(object);
};

OK, you can just optimise your code to get the result! There are many ways to do this which are cleaner, but I just wanted to get your pattern and apply it to that using JSON.stringify, just simply do something like this in your case:

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (JSON.stringify(a[i]) === JSON.stringify(obj)) {
            return true;
        }
    }
    return false;
}

Using idnexOf() it is a good solution, but you should hide embedded implementation indexOf() function which returns -1 with ~ operator:

function include(arr,obj) { 
    return !!(~arr.indexOf(obj)); 
} 
  1. Either use Array.indexOf(Object).
  2. With ECMA 7 one can use the Array.includes(Object).
  3. With ECMA 6 you can use Array.find(FunctionName) where FunctionName is a user defined function to search for the object in the array.

    Hope this helps!

I was working on a project that I needed a functionality like python set which removes all duplicates values and returns a new list, so I wrote this function maybe useful to someone

function set(arr) {
    var res = [];
    for (var i = 0; i < arr.length; i++) {
        if (res.indexOf(arr[i]) === -1) {
            res.push(arr[i]);
        }
    }
    return res;
}

It has one parameter: an array numbers of objects. Each object in the array has two integer properties denoted by x and y. The function must return a count of all such objects in the array that satisfy numbers.x == numbers.y

var numbers = [ { x: 1, y: 1 },
                 { x: 2, y: 3 },
                 { x: 3, y: 3 },
                 { x: 3, y: 4 },
                 { x: 4, y: 5 } ];
    count = 0; 
var n = numbers.length;
for (var i =0;i<n;i++)
{
  if(numbers[i].x==numbers[i].y)
  {count+=1;}
}

alert(count);

Not the answer you're looking for? Browse other questions tagged or ask your own question.