LoginSignup
10
10

More than 5 years have passed since last update.

高階関数を使ってパラメータ設定可能なエフェクタをつくる

Last updated at Posted at 2014-07-28

以前書いた サンプルに惑わされるな!KnockoutでUIエフェクトを使う際のベター・プラクティス という記事で、エフェクタを View 側のコードとして定義する方法をおすすめしました。

たとえばこんなの
window.effects = (function($) {
    var root = {}
      , list = root.list = {}
      ;
    list.fadeIn = function(elm) {
        $(elm).hide().fadeIn();
    };
    list.fadeOut = function(elm) {
        $(elm).fadeOut(300, function() { $(elm).remove() });
    };
    return root;
})(jQuery);

今回はそのエフェクタの、もうすこし突き進めた作り方を書いてみます。

高階関数とは

いかにも難しそうな名前ですが、単なる「関数を返却する関数」のことです。

高階関数
function example() {
    return function() {
        alert("example!");
    }
}

var e = example();
e(); // -> example!

高階関数でパラメータを扱う

内側の返却される関数で受け取る引数と、外側の高階関数で受け取る引数はそれぞれ使い道があります。

返却される関数の引数

つまり関数の実行時の引数です →param

function example() {
    return function(param) {
        alert(param);
    }
}

var e = example();
e("KnockoutJS"); // -> KnockoutJS
e("VueJS");      // -> VueJS

高階関数の引数

関数を生成するときに決定される引数です →param1

function example(param1) {
    return function(param2) {
        alert(param1 + param2);
    }
}

var e = example("hello "); // ここで決定
e("KnockoutJS"); // -> hello KnockoutJS
e("VueJS");      // -> hello VueJS

エフェクタへ応用

高階関数を使って、以下のフェードエフェクトのスピードをバインド時に設定できるようにしてみましょう。

Before
window.effects = (function($) {
    var root = {}
      , list = root.list = {}
      ;
    list.fadeIn = function(elm) {
        $(elm).hide().fadeIn();
    };
    list.fadeOut = function(elm) {
        $(elm).fadeOut(300, function() { $(elm).remove() });
    };
    return root;
})(jQuery);

↓↓↓

After
window.effects = (function($) {
    var root = {}
      , list = root.list = {}
      ;
    list.fadeIn = function(duration) {
        return function(elm) {
            $(elm).hide().fadeIn(duration);
        };
    };
    list.fadeOut = function(duration) {
        return function(elm) {
            $(elm).fadeOut(duration, function() { $(elm).remove() });
        };
    };
    return root;
})(jQuery);

duration という引数を受け取る高階関数に変更しました。
これをバインドするとき、以下のように引数を指定します。

View
<ul data-bind="foreach: {
                   data: items,
                   afterAdd: effects.list.fadeIn(200),
                   beforeRemove: effects.list.fadeOut(600) }">
    <li data-bind="text: $data"></li>
</ul>

上記の例では、リストにアイテムが追加されると200ミリ秒でフェードイン、
アイテムが削除されると600ミリ秒かけてフェードアウトします。

つまり、「View でバインドするときに決定されるパラメータ」を設けるために高階関数というものを使いました。effects.list.fadeIn(200) を実行すると、duration200 に決定されたエフェクタ関数が返却されます。その返却されたエフェクタ関数が afterAdd としてバインドされる、という寸法です。

フェード以外のエフェクタを実装する際にもいろいろと応用が利きますし、コンバータを実装する 際にも使えます。

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10