2

I'm working on the below code which works perfectly fine. But, ESLint suggest to use Object.keys instead of for..in loop. I tried to iterate the keys, do the search if the match found then return the object. It works with for..in but not with Object.keys. I tried to replace forEach with filter but didn't work for me. Any suggestions.

function searchObj (obj, query) {

  // Object.keys(obj).forEach(function(key){
  for (var key in obj) {
    var value = obj[key];
    if (typeof value === 'object') {
       return searchObj(value, query);
    }
    if (typeof value === 'string' && value.toLowerCase().indexOf(query.toLowerCase()) > -1) {
       return obj;
    }
  }
}

var demoData=[
  {id:1,desc:{original:'trans1'},date:'2017-07-16'},
  {id:2,desc:{original:'trans2'},date:'2017-07-12'},
  {id:3,desc:{original:'trans3'},date:'2017-07-11'},
  {id:4,desc:{original:'trans4'},date:'2017-07-15'}
];

var searchFilter = demoData.filter(function(obj){
     return searchObj(obj, 'trans1');
});
console.log(searchFilter);

here is the link JS bin

Murali N
  • 3,451
  • 4
  • 27
  • 38
  • Why not just turn off that rule if you're happy with your code the way it is? They're just guidelines/someone else's personal opinion how code should be written, not something set in stone. – Andy Aug 21 '17 at 13:46
  • 2
    You could try `Object.keys(…).find` or `for (… of Object.keys(…))`, but honestly [your loop is fine](https://stackoverflow.com/a/45014721/1048572). Just disable that es-lint rule! – Bergi Aug 21 '17 at 13:48
  • @Andy if it is the only best way rather than using `for..in` how would we do that. – Murali N Aug 21 '17 at 13:49
  • @MuraliPrasanth How do you run ESLint? – Bergi Aug 21 '17 at 13:51
  • 1
    https://eslint.org/docs/rules/no-restricted-syntax – Andy Aug 21 '17 at 13:52
  • @Bergi I have configured the ESLint to the project which watches the files automatically for any errors while I develop. – Murali N Aug 21 '17 at 13:53
  • 1
    @MuraliPrasanth you could disable it for a line `//eslint-disable-next-line` – Yury Tarabanko Aug 21 '17 at 13:58
  • 1
    @MuraliPrasanth If you have a ESLint configuration file, just put the rule to exclude there. – Bergi Aug 21 '17 at 14:01

2 Answers2

2

When you use Object.keys with forEach to iterate through the keys, you are passing a function as callback, so the return statements are for that callback function instead of searchObj.

Instead of returning the result from the forEach callback, you can store it in an external variable (accessed inside the forEach by means of closure), assign it in the forEach, and then return its value. Here I create a variable called foundObj for that:

function searchObj (obj, query) {
  var foundObj = null;

  Object.keys(obj).forEach(function(key) {
    var value = obj[key];
    if (typeof value === 'object') {
       foundObj = searchObj(value, query);
    }
    if (typeof value === 'string' && value.toLowerCase().indexOf(query.toLowerCase()) > -1) {
       foundObj = obj;
    }
  });

  return foundObj;
}

var demoData=[
  {id:1,desc:{original:'trans1'},date:'2017-07-16'},
  {id:2,desc:{original:'trans2'},date:'2017-07-12'},
  {id:3,desc:{original:'trans3'},date:'2017-07-11'},
  {id:4,desc:{original:'trans4'},date:'2017-07-15'}
];

var searchFilter = demoData.filter(function(obj){
     return searchObj(obj, 'trans1');
});
console.log(searchFilter);
Alberto Trindade Tavares
  • 10,056
  • 5
  • 38
  • 46
2

Since you don't really use found object just the fact it is there. You could use Array.prototype.some to avoid looping over every key in obj is you have already found it matches the search query.

function searchObj (obj, query) {
  return Object.keys(obj).some(function(key) {
    var value = obj[key];
    if (typeof value === 'object') {
       return searchObj(value, query);
    }
    
    return typeof value === 'string' && value.toLowerCase().indexOf(query.toLowerCase()) > -1;
  });
}

var demoData=[
  {id:1,desc:{original:'trans1'},date:'2017-07-16'},
  {id:2,desc:{original:'trans2'},date:'2017-07-12'},
  {id:3,desc:{original:'trans3'},date:'2017-07-11'},
  {id:4,desc:{original:'trans4'},date:'2017-07-15'}
];

var searchFilter = demoData.filter(function(obj){
     return searchObj(obj, 'trans1');
});
console.log(searchFilter);
Yury Tarabanko
  • 44,270
  • 9
  • 84
  • 98