3

別のパラメーターを受け入れるように Array.sort() を拡張したいと考えています。この質問にはクロージャーを使用した解決策があるため、このコードは機能します。

var create_comparator = function(c) {
  return function(a,b) { console.log(c); return a-b };
};

arr.sort( create_comparator('test') );

ただし、私の場合、次のように関数が既に定義されています。

var myComp1 = function(a,b) { console.log(c); return a-b };

事前定義された関数を返すことは機能しません:

var create_comparator = function(sortfn, c) {
  // Uncaught ReferenceError: c is not defined 
  return sortfn;      
};

var arr = [7, 4, 9, 2, 1];
arr.sort( create_comparator(myComp1, 'test') );

cこれは、元の関数が作成されたときに定義されていなかったためだと思います。新しいクロージャーを作成しようとreturn function(a,b) { sortfn(a,b); }しましたが、それも機能しません。

このセットアップを使用して、事前定義された関数で追加のパラメーターを使用できるようにすることは可能ですか? 問題の別の解決策はありますか?

4

4 に答える 4

2

あなたの例では、他のパラメーターで何をしているのかがはっきりしません。私はまだ突き刺して、パーシャルを使用することを提案します...のように:

var myComp1 = function (c, a, b) { console.log(c); return a-b };
arr.sort(myComp1.bind(null, "test"));

または、それをジェネレーター関数に抽象化したい場合は、次のようにします。

var myComp1 = function (c, a, b) { console.log(c); return a-b };

var create_comparator = function(sortfn, c) {
  return sortfn.bind(null, c);      
};

編集:別の方法!おそらく、あなたが達成しようとしていることに最適です。これの素晴らしい点は、並べ替え関数に任意の数の引数を追加できることです。これにより、追加のパラメーターがオプションになり、通常の並べ替えコンパレーターとしても使用できるようになります。

var myComp1 = function (a, b, c) { if (c) { console.log(c); } return a-b };

var create_comparator = function() {
    var sortfn = arguments[0], 
    partial = Array.prototype.slice.call(arguments, 1);

    return function() {
      var args = Array.prototype.slice.call(arguments).concat(partial);
      return sortfn.apply(null, args);
    }
};
于 2013-02-23T17:49:04.663 に答える
2

別のスコープmyComp1のローカル変数を閉じるようにさかのぼって変更することはできません。cそれは、単にクロージャーがどのように機能するか、またはローカル変数がどのように機能するかではありません。myComp1そもそも正しく定義する必要があります。

しかし、それができない場合は、一種の解決策があります。

スコープ内のローカル変数ではないmyComp1a を参照するため、実際に参照しているのはグローバル変数です。つまり、グローバル オブジェクトで指定されたプロパティを参照しています (ホストが Web ブラウザの場合)。つまり、ローカル変数をグローバル オブジェクトにコピーしてから呼び出すラッパー関数を作成できます。このようなもの:cc'c'windowmyComp1

var wrapped_myComp1 = function (a,b,c) {
    window.c = c;
    var ret = myComp1(a,b);
    delete window.c;
    return ret;
};

これは非常に醜く、この関数は再入不可であることを意味します (各呼び出しが他の呼び出しを上書きするためc) が、動作するはずです。

于 2013-02-23T17:50:08.147 に答える
0

関数 myComp1 の問題は、関数が未定義のグローバル変数 c を使用しようとすることです。JavaScript 関数には字句スコープがあります。これは、関数が定義されているスコープを使用することを意味します。そして、問題を解決するには閉鎖だけでは不十分です。このコードの id のように、c 変数をクロージャーに割り当ててみてください。

 var arr = [1,4,3,5,7,1,2],
        c;//it's a global variable, this is not a good approach. Good approach is change myComp1 definition, if you can.
    var myComp1 = function(a,b) { console.log(c); return a-b };

    var comp = function(prop) {
        c = prop; //this assignment push prop variable to global variable c, that uses in your function
        return myComp1;
    }

console.log(arr.sort(comp('additional_param')));
于 2013-02-23T17:59:55.203 に答える
0

これはうまくいきます

var c = 'test'
var myComp1 = function(a,b) { console.log(c); return a-b };

arr.sort( myComp1 );

ここで、クロージャーは c を定義します (ただし、上記のように定義する必要があります。c を定義していない場合は、エラーが発生します)。

于 2013-02-23T18:00:04.877 に答える