0

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

Daniel
  • 611
  • 5
  • 20
  • 1
    how `ladders` relates with `findWhere`? If it's passed as `array`, then what is `criteria` value? – RomanPerekhrest Feb 05 '17 at 21:01
  • 1
    I don't see how `Object.keys()` (that is returning an array) can be used as an index. – haim770 Feb 05 '17 at 21:03
  • It is used as a key to index into the array, [which is possible as shown here](http://stackoverflow.com/a/10174080/3492895), it seems to just `.toString()` the array or something. It would be easier to try to understanding why it would be useful if we had some more context. – Winestone Feb 05 '17 at 21:04
  • The last line is just `}`, it works by closing the function ? – adeneo Feb 05 '17 at 21:05
  • Also, [bracket notation](http://stackoverflow.com/questions/4968406/javascript-property-access-dot-notation-vs-brackets) accesses an array or object by using the key/index. – adeneo Feb 05 '17 at 21:06
  • Possible duplicate of [Is JavaScript array index a string or an integer?](https://stackoverflow.com/questions/27537677/is-javascript-array-index-a-string-or-an-integer) – Chiri Vulpes Jul 01 '17 at 06:22

3 Answers3

2

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 }));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

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)]

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
1

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;
}
Tolgahan Albayrak
  • 3,118
  • 1
  • 25
  • 28