2
\$\begingroup\$

I am using the following code in order to retrieve the index for an object stored in a JavaScript array.

Scripts works fine, but I would like your opinion regarding performance.

Also would like to know also if using [].map() could be more appropriate of [].some().

http://jsbin.com/nasiyiyavi/1/

var data = [{ id: 3 }, { id: 4 }, { id: 1 }, { id: 0 }, { id: 2 }];

function findIndexInData(optionsArg) {
    var options = {
        data: optionsArg.data,
        where: optionsArg.where,
        what: optionsArg.what
    },
    result = -1;
    options.data.some(function (item, i) {
        if (item[options.where] === options.what) {
            result = i;
            return true;
        }
    });
    return result;
}
alert(findIndexInData({ data: data, where: 'id', what: 2 }));
\$\endgroup\$
4
\$\begingroup\$

Eric Blade is correct that this is a perfect use-case for findIndex. But I'd like to comment on your current code:

  • Why are you using an object to pass the arguments? You need all three components (data, where, and what), whereas a object usually means each part is optional. If you want to make it clear that all the parts are required, then just use regular arguments:

    function findIndexInData(data, property, value)
    

    I'm also naming them property and value, since that's the usual name for such things (or key and value).

  • I'm not sure what the purpose of this part is:

    var options = {
        data: optionsArg.data,
        where: optionsArg.where,
        what: optionsArg.what
    }
    

    So you start with the optionsArg object, and from that you create... basically an identical object. Why? What's the point?

  • I'd probably just use a plain old for loop rather than some

  • And if you do that, you don't need the result variable. Right now, you're modifying the closed-over result variable, which, while ok, isn't too pretty.

I end up with this, which seems simpler.

function findIndexInData(data, property, value) {
  for(var i = 0, l = data.length ; i < l ; i++) {
    if(data[i][property] === value) {
      return i;
    }
  }
  return -1;
}

But again, the simplest is probably to just use findIndex, as Eric Blade suggests.

\$\endgroup\$
5
\$\begingroup\$

I think the best way of doing that would be using the new ES6 function Array.prototype.findIndex:

data.findIndex(function(obj) { return obj[where] === what; })

If you don't have that function, there are good polyfills at MDN and NPM.

(if you do have full ES6, you apparently could also do

data.findIndex(obj => obj[where] === what)

but i'm still learning how that syntax works so i may be wrong there)

\$\endgroup\$
  • \$\begingroup\$ does the whole "needing polyfill" thing apply to node? \$\endgroup\$ – PirateApp Jan 6 at 12:45
  • \$\begingroup\$ Array.prototype.findIndex was implemented back in node 0.12.x, so you probably don't need a polyfill to anyone using it now \$\endgroup\$ – Eric Blade Jan 17 at 0:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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