2

Im trying to get indexOf of a object after its pushed inside a array. This is not returning the same value back as i do indexOf whenever objext is allready in the array.

SCENARIO


var arr = [];
setInterval(function() {
	var path = { one: "f00"};
    if (typeof path !== "undefined") {
        if (arr.indexOf(path) === -1) {
            console.log("Not Exists!!")
            arr.push(path)
        } else {
            console.log("Exists!!")
        }
    }
	console.log(arr)
}, 2000)

What is the different between the working of

10
  • 1
    You're using an object in the indexOf, it might not know how to compare them Commented Mar 13, 2017 at 16:51
  • 2
    @JohnSmiths because you're passing a direct reference to the object instead of another object that has the same data Commented Mar 13, 2017 at 16:52
  • 2
    Possible duplicate of Javascript oddness with array of objects and indexOf Commented Mar 13, 2017 at 16:53
  • 1
    @MikeMcCaughan no its not, the first console.log returns correct value "0" and the second console shows -1 Commented Mar 13, 2017 at 16:54
  • 1
    Possible duplicate of Javascript array.indexOf doesn't search objects Commented Mar 13, 2017 at 16:54

2 Answers 2

1

The issue is that JavaScript doesn't do a deep compare of objects, so it doesn't recognize them as the same.

var a = { name: 'foo' }
var b = { name: 'foo' }
a === b // false

However, since you have access to the object before the insert, you can save a reference to it, and then search for that reference:

var arr = []
var obj = { path: 'foo' }
arr.push(obj)
arr.indexOf(obj) // 0

This is because indexOf uses the strict equality === comparison. So in this case, the references to obj and the object at arr[0] are the same.

Edit

Based on your changed question, here is a way to write your function to do what you want:

var arr = [];

function findAdnSet(obj) {
  var index = arr.indexOf(obj);

  if (index !== -1) {
    return index;
  } else {
    arr.push(obj);
    return arr.length - 1; // No reason to use indexOf here, you know the location since you pushed it, meaning it HAS to be the last element in the array
  }
}

var path = { name: 'foo' };
findAndSet(path);

A more robust option than using indexOf since your function might not always have a good reference available is to use find/findIndex:

var arr = [];

function findAndSet(obj) {
  var index = arr.findIndex(function(item) {
    if (item.name === 'foo') {
      return true;
    }
  });

  if (index) { // findIndex returns `undefined` if nothing is found, not -1
    return index;
  } else {
    arr.push(obj);
    return arr.length - 1;
  }
}

// You don't need a reference anymore since our method is doing a "deep" compare of the objects
findAndSet({ name: 'foo' });
Sign up to request clarification or add additional context in comments.

5 Comments

I edited my code, can you show example with that one. Why i dont get ! -1
The reference to path changes each time the function is run, since you redefine path each time the function is run. You'll have to save path before you define the setTimeout call.
Is it because i'm using setInterval and forEach() to get the path ?
Well, I don't see a forEach anywhere in your code, but yes to the setInterval. Every time you call the function everything inside is happening for essentially the first time. When the function ends in-between runs the internal scope (memory) of the function is lost.
I have added two new examples that should help you.
0

The first time you do indexOf you push and search for the object 'path' so it is found. The second time you create an object and add push it to the array, and then search for another new object (which happens to have the same values), but since it is not the same object that you pushed it is not found.

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.