Javascript: переменная не является неопределенной, но при возврате возвращается неопределенной

1

В фрагменте ниже, перед return(res), я запишу его, и он не undefined

но каким-то образом он возвращается как undefined.

Что я делаю неправильно?

filterData = (inputData, searchedKey) => {
  inputData.forEach((data, index) => {
    if(data){
      if(data.hasOwnProperty(searchedKey)){
        const res = data[searchedKey]
        console.log(res) /// logs the results
        return(res) /// returns undefined
      }
      var dataToProcess = [];

      var fieldKeys = Object.keys(data)
      fieldKeys = fieldKeys.filter((field, index) => !field.includes("#"))
      fieldKeys.forEach((key, index) => {
        dataToProcess.push(data[key]);
      })
      this.filterData(dataToProcess, searchedKey)
    }
  })
}

console.log(this.filterData([{"#name": "foo", "#type": "bar"}], "#type"))
Теги:

2 ответа

1
Лучший ответ

Некоторые вопросы:

  • forEach не возвращает ничего, кроме undefined, поэтому возврат значения в его функцию обратного вызова не делает ничего полезного.
  • Ваша функция не возвращает значение
  • Возвращаемое значение рекурсивного вызова не используется.
  • if (data) недостаточно хороши, чтобы убедиться, что data являются объектом. Например, это также верно для ненулевого числа. Вместо этого используйте Object(data) === data.
  • Поскольку может быть несколько совпадений (во вложенном объекте ввода), ваша функция должна возвращать массив, что также и то, что можно было бы ожидать при просмотре имени вашей функции. Также метод filter стандартных массивов возвращает массив. Таким образом, это соответствовало бы этому.

Вот как вы могли бы заставить его работать:

var filterData = (inputData, searchedKey) => {
    inputData = inputData.filter( data => Object(data) === data );
    return !inputData.length ? [] :
        inputData.filter( data => data.hasOwnProperty(searchedKey) )
            .map( data => data[searchedKey] )
            // Add the results from recursion:
            .concat(filterData([].concat(...
                inputData.map( data =>
                    Object.keys(data)
                        .filter( key => !key.startsWith("#") )
                        .map( key => data[key] )
                )
            ), searchedKey));
};

var data = [{
    "#name": "foo", 
    "#title": "mr",
    "deeper": [{
        "#nope": "bad",
        "deepest": [{
            "nothing_here": null,
            "#type": "deeper bar",
        }]
    }, {
        "#type": "bar",
    }]
}];

console.log(filterData(data, "#type"));

Если вам нужно только первое совпадение, используйте этот вариант:

var filterData = (inputData, searchedKey) => {
    inputData = inputData.filter( data => Object(data) === data );
    var res = inputData.find( data => data.hasOwnProperty(searchedKey) );
    return res !== undefined ? res[searchedKey] :
        // Try in nested objects:
        filterData([].concat(...
            inputData.map( data =>
                Object.keys(data)
                    .filter( key => !key.startsWith("#") )
                    .map( key => data[key] )
            )
        ), searchedKey);
};

var data = [{
    "#name": "foo", 
    "#title": "mr",
    "deeper": [{
        "#nope": "bad",
        "deepest": [{
            "nothing_here": null,
            "#type": "deeper bar",
        }]
    }, {
        "#type": "bar",
    }]
}];

console.log(filterData(data, "#type"));
  • 0
    Спасибо за Ваш ответ. Это мне очень помогло. Но мне нужно вернуться, как только я найду первый матч, мне не нужно больше одного результата. будет много матчей, мне просто нужен первый матч. Как я могу этого достичь? Благодарю.
  • 1
    Пожалуйста. Я добавил решение для получения первого матча.
0

Это то, чего вы хотите достичь?

filterData = (inputData, searchedKey) => {
  return inputData.map((data, index) => {
    if(data){
      if(data.hasOwnProperty(searchedKey)){
        const res = data[searchedKey]
        console.log(res) /// logs the results
        return(res) /// returns undefined
      }
      var dataToProcess = [];

      var fieldKeys = Object.keys(data)
      fieldKeys = fieldKeys.filter((field, index) => !field.includes("#"))
      fieldKeys.forEach((key, index) => {
        dataToProcess.push(data[key]);
      })
      this.filterData(dataToProcess, searchedKey)
    }
  })
}

console.log(this.filterData([{"#name": "foo", "#type": "bar"}], "#type"))

Используйте Array#map(), это очень полезно во многих случаях.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню