2017-06-08 20 views
1

を返される、return(res)前に、私はそれをログに記録し、それがundefinedJavascriptを:変数が未定義ではなく、戻しながら、以下のスニペットでは、未定義の

ではないのですが、どういうわけか、それは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"))

+1

forEachからどのくらい「返す」計画をしていますか? – Dellirium

+0

'filterData'は何も返さないので、論理的には' undefined'を出力します – trincot

+0

return(res)は何ですか? resを入力とした関数呼び出し?戻り関数はどこですか?あなたのコードを補完、あるいはむしろreturnキーワード 編集を使用してください:まあ、私はその有効なreturn文を知らなかっ:リターン(何か) – Ursache

答えて

1

いくつかの問題:

  • forEachundefinedよりも何かを返さないので、そのコールバック関数に値を返すことは何も有効ではありません。
  • 関数が値を返さない
  • 再帰呼び出しの戻り値は使用されません。
  • 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つ以上の結果を必要としない。多くの試合があるだろう、私は最初の試合が必要です。それをどうすれば実現できますか?ありがとう。 – Ataomega

+1

ようこそ。私は最初にマッチするためのソリューションを追加しました。 – trincot

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()、それは多くの場合、かなり便利です。

関連する問題