1

I have seen multiple examples where indexOf is used within Vue to select an object from an array of objects like this:

Script:

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!',
    items: [
        {
        id: 1,
        name: 'test'
      },
      {
        id: 2,
        name: 'hello'
      },
      {
        id: 3,
        name: 'world'
      }
    ]
  },
  methods: {
    deleteItem(item) {
      console.log(this.items.indexOf(item));
      // splice the item.
    }
  }
})

Template:

<script src="https://unpkg.com/vue"></script>

<div id="app">
  <p>{{ message }}</p>

  <ul>
    <li v-for="item in items" @click=deleteItem(item)>
      {{ item.name }}
    </li>
  </ul>
</div>

https://jsfiddle.net/5gwtyv3h/

Now I am wondering this is even possible. If I go into my console and simply do this:

const items = [
    {
        id: 1,
        name: 'test'
    },
    {
        id: 2,
        name: 'hello'
    },
    {
        id: 3,
        name: 'world'
    }
];

items.indexOf({ id: 1, name: 'test'});

I get -1 because the item can not be found. Is Vue doing something that makes this possible or I missing something else here?

5
  • 1
    Your test always returns -1 because the object literal you're passing is not in the items array. Object comparisons don't involve the object contents; they're based on the object references. Commented Feb 5, 2018 at 15:41
  • 1
    Possible duplicate of Difference Between indexOf and findIndex function of array Commented Feb 5, 2018 at 15:41
  • So it works with the object references? I find that extremely hard to find online. Even the mozilla page does not seem to mention anything about it: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Feb 5, 2018 at 15:43
  • @str the question you marked as a duplicate says nothing about references or looking for objects. Commented Feb 5, 2018 at 15:44
  • @Stephan-v The answer mentions "primitive types" and "non-primitive types (e.g. objects)". Commented Feb 5, 2018 at 15:49

1 Answer 1

3

You will have to cache the object that you add to the Array or do a deep find() or findIndex() comparison.

For Objects compared with indexOf, they have to be the exact same Object, meaning, they must refer to the exact same Object instance.

const a = {
    foo: "bar"
  },
  b = {
    foo: "bar"
  };

console.log(a === b); // false

Consider this:

const a = {
    foo: "bar"
  },
  b = {
    foo: "bar"
  };

const c = [a, b];

console.log(c.indexOf({
  foo: "bar"
})); // -1 since the Object you **just** made won't be in the array

console.log(c.indexOf(a)); // 0 you're looking for the right object by reference

console.log(c.findIndex(i => i.foo === "bar")); // 0 again since it does a deep compare

// Succinct deep compare using lodash
console.log(_.findIndex(c, i => _.isEqual(i, {
  foo: "bar"
}))); // 0 again but deep compare logic is encapsulated
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

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

1 Comment

Thanks, I feel this is not explained enough. Documentation about indexOf seems to be lacking in this part.

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.