JavaScript find helper

There is an exercise on Udemy where I have found this solution.

var ladders = [
  { id: 1, height: 8  }, 
  { id: 2, height: 10 },
  { id: 3, height: 20 }, 
  { id: 4, height: 25 }, 
  { id: 5, height: 30 }, 
  { id: 6, height: 40 }, 
];

function findWhere(array, criteria) {

  return array.find(function(el) {

    return el[Object.keys(criteria)] === criteria[Object.keys(criteria)];
  });
}

Could you explain how the last line work? I know what the Object.keys does but I do not understand why it is between square brackets.

Thank you

Upvotes: 0

Views: 497

Answers (3)

Tolgahan Albayrak
Tolgahan Albayrak

Reputation: 3206

Because Object.keys returns array and when you use an array as index, it is converted to string. If you have a single element in an array then string output will be equal to that element's toString value.

But this is not a good solution. It works only if your criteria has single key.

See the reason below:

function findWhere(array, criteria) {
  return array.find(function(el) {
    return el[Object.keys(criteria)] === criteria[Object.keys(criteria)];
  });
}

var ladders = [{ id: 1, height: 8 }, { id: 2, height: 10 }, { id: 3, height: 20 }, { id: 4, height: 25 }, { id: 5, height: 30 }, { id: 6, height: 40 }];

console.log(findWhere(ladders, { id: 2})); // this line works right
console.log(findWhere(ladders, { id: 2, height:10 })); // this line will result invalid

So, the expected find method should be like below one:

function findWhere(array, criteria) {
  return array.find(el => 
                    Object.keys(criteria)
                    .every(key => criteria[key] === el[key])
                   );
}

var ladders = [{ id: 1, height: 8 }, { id: 2, height: 10 }, { id: 3, height: 20 }, { id: 4, height: 25 }, { id: 5, height: 30 }, { id: 6, height: 40 }];

console.log(findWhere(ladders, { id: 2})); // this line works right
console.log(findWhere(ladders, { id: 2, height:3 })); // this line works right too (undefined expected)
console.log(findWhere(ladders, { id: 2, height:10 })); // this line works right too (id:2 expected)
console.log(findWhere(ladders, { height:25 })); // this line works right too (id:4 expected)
.as-console-wrapper{
  min-height:100%;
  max-height:100%;
  top:0;
}

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386680

The line

return el[Object.keys(criteria)] === criteria[Object.keys(criteria)];
//        'id'                                'id'
//     el['id']                  === criteria['id']
//     2                         === 2

takes basically first the key of the object, in both sides and wrap it in the left side with an element of the array and on the right side with the object criteria.

function findWhere(array, criteria) {
  return array.find(function(el) {
    return el[Object.keys(criteria)] === criteria[Object.keys(criteria)];
  });
}

var ladders = [{ id: 1, height: 8 }, { id: 2, height: 10 }, { id: 3, height: 20 }, { id: 4, height: 25 }, { id: 5, height: 30 }, { id: 6, height: 40 }];

console.log(findWhere(ladders, { id: 2 }));

Upvotes: 2

Scott Marcus
Scott Marcus

Reputation: 65825

The find() array method takes a function as an argument in order to work. That function will automatically be provided a reference to the array element that is being iterated over (which is represented here by the parameter el), but in this case the element will be one of the objects in the original array.

In order to get a property value, when the property name is in string form, you must use bracket notation ([propertyNameAsString]), so:

  • el is the object reference
  • [Object.keys(criteria)] is the property name as a string being passed using bracket notation

The result is the value of the property, which is then being compared against criteria[Object.keys(criteria)]

Upvotes: 1

Related Questions