2017-08-16 21 views
5

私は、フォルダツリーを検索し、選択したフォルダの親フォルダを見つける関数を持っています。javascript/Polymerで再帰関数を呼び出せません

ここに関数があります。

 getParentFolder: function (searchroot, childFolder) { 
      searchroot.subfolders.forEach(function (folder) { 
       if (folder.key == childFolder.key) { 
        return searchroot; 
       } 
       else { 
        if (folder.subfolders) { 
         return this.getParentFolder(folder, childFolder); 
        } 
       } 
      }); 
     } 

私はそれは単に私だけを与えるthis.getParentFolder(rootFolder, childFolder);

でこれを呼び出す:キャッチされない例外TypeError:this.getParentFolderはなぜこれを機能 ではないでしょうか?私は他の関数を呼び出すと同じファイルで、彼らは完全に正常に動作します。これは私が呼び出すことができない唯一の機能です。再帰のためですか?

答えて

5

forEachメソッド内でコンテキストを変更するときには、thisを変数に保持する必要があります。

getParentFolder: function(searchroot, childFolder) { 
    var self = this; 
    searchroot.subfolders.forEach(function(folder) { 
    if (folder.key == childFolder.key) { 
     return searchroot; 
    } else { 
     if (folder.subfolders) { 
     return self.getParentFolder(folder, childFolder); 
     } 
    } 
    }); 
} 

また、returnステートメントは、あなたが望むように動作しません。私はあなたがループのために使って配列を列挙することをお勧めします:

getParentFolder: function(searchroot, childFolder) { 
    for (var i = 0; i < searchroot.subfolders.length; i++) { 
    var folder = searchroot.subfolders[i]; 
    if (folder.key == childFolder.key) { 
     return searchroot; 
    } else { 
     if (folder.subfolders) { 
     return self.getParentFolder(folder, childFolder); 
     } 
    } 
    } 
} 
+0

これは、JavaScriptの性質上、私はこれを何回かのループで呼び出すたびに、毎回これを自己に再割り当てする必要がありますか? – nanobots

+1

あなたはあなたの主なオブジェクトを追跡したい場合は絶対に。あるいは、['bind'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) –

+1

@nanobotsを使用すると、外側の' this 'forEach'の引数として' self'を使う必要がありません。 –

3

問題は、あなたのthisはあなたがforEachに渡された関数の内部で異なることです。あなたは、内側の関数に外thisをバインドする必要があります。

MDNの Array.prototype.forEach()から
getParentFolder: function(searchroot, childFolder) { 
    searchroot.subfolders.forEach(function(folder) { 
    if (folder.key == childFolder.key) { 
     return searchroot; 
    } else { 
     if (folder.subfolders) { 
     return this.getParentFolder(folder, childFolder); 
     } 
    } 
    }, this); // pass in outer this as context for inner function 
} 

Syntax:

arr.forEach(function callback(currentValue, index, array) { 
    //your iterator 
}[, thisArg]); 

ES6を使用して代替ソリューション:

コメントに記載されているmishuと同様に、新しいES6矢印構文もこの問題を解決します。 ES6であなたのコードは次のようになります:

getParentFolder: function(searchroot, childFolder) { 
    searchroot.subfolders.forEach((folder) => { 
    if (folder.key == childFolder.key) { 
     return searchroot; 
    } else { 
     if (folder.subfolders) { 
     return this.getParentFolder(folder, childFolder); 
     } 
    } 
    }); 
} 

アロー関数は(MDNを参照)thisを結合しないES6あるので、外thisを矢印関数内からアクセスすることができます。

まだすべてのブラウザが矢印機能をサポートしているとは限りません(Browser compatibility on MDNを参照)。古いブラウザをサポートするには、Babelを使用してES6からES5に移行することができます。

+2

新しいES6矢印構文もこの問題を解決しません。なぜなら 'this'にバインディングがないからです。 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_binding_of_this – mishu

+1

@mishu、はい、それを含む私の答えが更新されました。良い提案! –

関連する問題