1

javasciptでオブジェクトの配列を並べ替えようとしています。ソート順自体は、オブジェクトのプロパティと単一の外部変数の値という2つの要因に依存します。array.sort(sortFunction)を使用してカスタム関数を挿入できることは知っていますが、外部変数(ソート中に固定される)に応じて異なる関数を使用する必要があります。

実際の問題ははるかに複雑ですが、問題を示す最小限のテストケースに並べ替えを減らし、「降順/昇順」パラメーターを挿入しようとしました。結果をreverse()できることはわかっていますが、ここでは問題にはなりません。

コードは次のとおりです。

var ar = [ 10, 3, 5, 17 ];
var ns = new nsort();
ar.sort(ns.sort);
console.log(ar);

function nsort()
{
    this.desc = true;
    this.sort = function(a,b) {
        console.log(this.desc);
        if (this.desc)
            return b-a;
        else
            return a-b;
    }
}

これが出力です(Node.jsを使用)

undefined
undefined
undefined
undefined
[ 3, 5, 10, 17 ]

配列の並べ替えコードは、並べ替え中に親オブジェクトの外部に関数を抽出するようです。

なぜこれが起こっているのか、そしてそれを行うための適切な方法は何でしょうか?

更新:私はそれを機能させる方法を見つけました:

var ar = [ 10, 3, 5, 17 ];
var ns = new nsort(true);
ar.sort(ns.sort);
console.log(ar);

function nsort(desc)
{
    this.sort = function(a,b) {
        if (desc)
            return b-a;
        else
            return a-b;
    }
}

これは良い考えですか?それとももっと良いものがありますか?

4

3 に答える 3

3

あなたns.sortはその呼び出しコンテキストを失っています。つまり、に渡すと、オブジェクト.sort()との接続はなくなります。ns

コンストラクター内の変数がオブジェクトを指すようにし、sort関数が変数を参照するようにすることで、関数がオブジェクトを直接参照するようにすることができます。

function nsort()
{
    this.desc = true;
    var self = this;
    this.sort = function(a,b) {
        console.log(self.desc);
        if (self.desc)
            return b-a;
        else
            return a-b;
    }
}

または、NodeJSのような最新の環境にいる場合はFunction.prototype.bind()、呼び出し元のコンテキスト値を関数に永続的に付加するために使用できます。

function nsort()
{
    this.desc = true;
    this.sort = function(a,b) {
        console.log(this.desc);
        if (this.desc)
            return b-a;
        else
            return a-b;
    }.bind(this);
}
于 2012-10-27T20:28:52.017 に答える
1

を使用する必要がありますbindhttp://jsfiddle.net/fub49/を参照してください。

var ar = [ 10, 3, 5, 17 ];
var ns = new nsort();
ar.sort(ns.sort.bind(ns));
console.log(ar);

function nsort() {
    this.desc = true;
    this.sort = function(a,b) {
        console.log(this.desc);
        if (this.desc)
            return b-a;
        else
            return a-b;
    }
}

一言で言えば、これは「ソート関数を使用しますが、その関数が式の値にns.sort内部的に使用するように呼び出します。nsthis

于 2012-10-27T20:31:41.143 に答える
1

代わりに、bindこのパターンを使用することもできます(クロージャーを使用):

function nsort(desc)
{
   desc = desc || false;
   this.setDesc = function(val){desc = val; return this;}
   this.sort = function(a,b) {
        return desc ? b-a : a-b;
   }
}
var ar = [ 10, 3, 5, 17 ]
   ,ns = new nsort();
ar.sort(ns.sort);
console.log(ar); //=> [ 3, 5, 10, 17 ]
ar.sort(ns.setDesc(true).sort);
console.log(ar); //=> [ 17, 10, 5, 3 ]

楽しみのために、ここに単純化、より「機能的」で、呼び出しコンテキストの問題を回避します。

function nsort(desc)
{
  return function(a,b){
       return desc ? b-a : a-b;
  };
}
var ar = [ 10, 3, 5, 17 ];
console.log( ar.sort(nsort()) );     //=> [ 3, 5, 10, 17 ]
console.log( ar.sort(nsort(true)) ); //=> [ 17, 10, 5, 3 ]
于 2012-10-27T20:53:06.387 に答える