2

関数の引数へのマップを作成したいと思います。このマップは動的に更新されます。最後に、すべての関数が対応する引数で呼び出されます。

function foo1(x) { 
    //do something with x
}

function foo2(x) { 
    //do something else with x
}

var map = {};
map[foo1] = [1,2,3];  //this array is updated dynamically in my code
map[foo2] = [4,5,6];

// I want to call foo1 and foo2 with their [1,2,3] and [4,5,6] arguments respectively.

私は2つのアプローチを試しました:

  • マップのキーとしてfoo1(メソッドを使用して) 文字列に変換されます。toString()その後、Function コンストラクターを使用して、この文字列から関数を取得します。しかし、これがパフォーマンスに影響するかどうかは心配です。
// This works. But concerned about the performance

map[foo1.toString()] = [1,2,3];

for(i in map){
    var fn = Function( 'return '+ i)();
    fn(map[i]);
}
  • 関数とそれぞれの引数をラップするオブジェクトを次のように保存します。
   { fn : foo1 , args : [1,2,3] }
   { fn : foo2 , args : [4,5,6] }

ここでは、関数定義全体ではなく、関数への参照を保存します。しかし、さらに引数を追加するには、配列全体をトラバースする必要があります。

このマップを維持するためのより良い方法はありますか? 上記のアプローチの欠点は何ですか?

アップデート

「どのような状況でこれが必要になるか」という質問への回答:

引数から関数へのマップを維持しています。動的に更新します。コードの後半で、リバース マップを作成し、すべての引数を指定して関数を呼び出します。

例:

1 -> foo1
2 -> foo2
3 -> foo1,foo2
4 -> foo1
... and so on.

次に、次のような逆マップを作成します。

foo1 -> [1,3,4...]
foo2 -> [2,3,...]

そして最後に呼び出します:

foo1( [1,3,4...])

foo2( [2,3,...])
4

4 に答える 4

3

JavaScript のオブジェクトは文字列のみをキーとして持つことができるため、使用map[foo1]は実質的に と同じですmap[foo1.toString()]。これらは両方とも、あなたが気づいていない問題を抱えています: それらは閉じられた変数を破棄します。

function makeCounter() {
    var counter = 0;
    return function() { return ++counter; }
}

私が持っている場合

var myCounter = makeCounter();

thenmyCounter.toString()になりfunction() { return ++counter; }Functionコンストラクターでそれを再構成しようとすると、間違ったcounter参照が発生します。

本当に、最良のオプションは、関数の名前をプロパティとして使用し、値として、提案したようなオブジェクトを使用することです。

var map = {};
map['foo1'] = { fn: foo1, args: [1, 2, 3] };

その後、後でさらに引数を追加したい場合は、かなり明白です。

map['foo1'].args.push(4);

それらすべてを呼び出すには、次のようなものを使用できます。

for(var functionName in map) {
    if(!Object.prototype.hasOwnProperty.call(map, functionName)) {
        continue;
    }
    map[functionName].fn.apply(null, map[functionName].args);
}
于 2013-04-27T02:55:55.317 に答える
2

オブジェクト (または関数) をキーとして使用するには、Harmony (EcmaScript 6)WeakMapまたはMap. どちらも現在実験段階であり、どちらも Firefox で利用できます。WeakMapChromeでも利用できると思います(適切なフラグ設定で?)。

プラットフォームが WeakMap をサポートしていて、それらを組み込むことを選択した場合、その使用法は非常に簡単です。

var myWeakMap=new WeakMap();
myWeakMap.get(key [, defaultValue]);
myWeakMap.set(key, value);
myWeakMap.has(key);
myWeakMap.delete(key);
myWeakMap.clear();

詳細情報 (MDN 参照はリストされていないように見えることに注意してください):

また、別の方法として、関数の配列を使用し、indexOf を使用して関数のインデックスを取得し、そのインデックスを持つ別の配列のパラメーターにアクセスすることもできます。

function a(){}
function b(){}
var x=[a,b].indexOf(b);  //x=1
于 2013-04-27T03:23:38.573 に答える
1

私の質問の下のコメントでこれを提案してくれた Dagg Nabbit の功績。

「関数はプロパティを持つことができることを忘れないでください。常に関数を配列に格納し、配列内のインデックスをプロパティとして関数にアタッチし、その方法で検索することができます。」- ダグ・ナビット

次のargs-to-callback引数のマップを検討してください。

マップ:

1 -> foo1
2 -> foo1,foo2
3 -> foo2

目的は、次のようなコールバックから引数へのマップ (逆マップ)を構築することです。

コールバックマップ:

foo1 -> [1,2]
foo2 -> [2,3]

アプローチ :

var allArgsPossible = [1,2,3]

// contains the list of callbacks to be called
var callbackArray = [];  

//maps the callback index in callbackArray to the callback's arguments
//callbackMap[index] = args means callbackArray[index] will be called with parameter "args" 
var callbackMap = {};

for( i in allArgsPossible)
{
    var item = allArgsPossible[i];
    var callbacks =  map[ item  ];
    for(j in callbacks)
    {
        var callback = callbacks[j];

        if(callback.index == undefined)
        {
            var index = callbackArray.length;
            // adding a new property "index" to the callback
            callback.index = index;
            callbackMap[index] = [item];
            //create a new entry in callbackArray
            callbackArray.push(callback);
        }
        else
        {
            callbackMap[callback.index].push(item);
        }
    }
}

console.log(JSON.stringify(callbackMap));

for( i in callbackArray)
{
    var callback = callbackArray[i];
    //get arguments from our reverse map
    var args = callbackMap[callback.index];
    // Bingo ! 
    callback(args);
}

ここで全体像を得ることができます: http://jsfiddle.net/kyvUA/2/

ここで注意すべき点の 1 つは、コールバック関数が他の目的のために既に " index " プロパティを持っている可能性があることです。それが懸念される場合は、ランダムな文字列を生成し、インデックスを値としてコールバックにこのプロパティを格納できます。( @plalx の提案による)

乾杯 !

于 2013-04-27T09:03:23.563 に答える