2015-09-12 14 views
5

関数型プログラミングの詳細については、アンダースコアのドキュメントを参照し、より頻繁に使用される関数の独自のバージョンを作成しようとしました。"memoize"関数の実装と理解

"memoize"に出くわす - 私は頭の中で頭を折るのに問題があり、Crockfordの 'The Good Parts'でいくつかの情報を見つけました。

_.memoize = function(func) { 
    // 'cache' object is used to hold the result of the memoized fn's call 
    var cache = {}; 
    var recur = function(n) { 
     var result = cache[n]; 
     if (typeof result === 'undefined') { 
     result = func.apply(this, arguments); 
     cache[n] = result; 
     } 
     return result; 
    } 
    return recur; 
    }; 

あなたは.applyの私の使用も必要だったなら、私は理解して助けてください可能性があり、任意のコアの改善があった場合、私は、このコードにすることができますか?本当に助けに感謝!

+0

はい、funcに何個の引数があるのか​​分からないので、applyの使用が必要です –

+0

これはあなた自身で書いたコードなのですか?あなたはそれについて理解していないことは何もありません。またはアンダースコアのどの部分を理解していないのですか? – Bergi

+0

@Bergi - 私はこの解決策に到達することができましたが、私ができるエラーや改善があるかどうかを見たいと思っていました。私が下で述べたように、私はtypeofの使用を変更し、代わりにhasOwnPropertyに依存しています。しかし、私はメモ帳機能が必要以上に実行されるのを防ぐ方法を見つけようとしています。 – tsaiDavid

答えて

6

正しさを持ついくつかの明白な問題があります。

1)あなただけの最初引数の値に基づいて結果をキャッシュするので、異なる引数を持つ関数を呼び出すと、間違った結果が生成されます!

let add = memoize((a, b) => a + b) 
add(1, 2) 
> 3 
add(1, 3) 
> 3 

あなたがまだ呼び出されていない機能を表現するためにundefinedを使用し2)、しかしundefinedは、有効な戻り値です。副作用が二度起こるかを参照してください:あなたが代わりに何かがキャッシュ内にあるかどうかを検出するためにcache.hasOwnPropertyを使用することができます

let log = memoize(() => console.log('hello')) 
log() 
> hello 
log() 
> hello 

テストスイートを作成することをお勧めします。テストはこれらのバグを見つける上で非常に貴重です。あなたの機能が適切に機能しないかもしれない他の辺のケースを考えてみてください。このようなスタンドアロンのユーティリティは、実際にテスト駆動型のコーディングに役立ちます。

+0

お返事ありがとうございました。非常に役に立ちます。私は先に進み、 '未定義'を使用すると有効な戻り値を返すことができることを考慮してリファクタリングしました。代わりに 'if(!cache.hasOwnProperty(result)){' – tsaiDavid

+1

と置き換えてください。 'var log = memoize(console.log.bind(console)); log( "hasOwnProperty"); log( "hasOwnProperty"); ' – Bergi