为Javascript数组排序注入对象而不是函数

为Javascript数组排序注入对象而不是函数,javascript,node.js,sorting,v8,Javascript,Node.js,Sorting,V8,我正在尝试对javascipt中的对象数组进行排序。排序顺序本身取决于两个因素:对象的属性和单个外部变量的值。我知道我可以使用array.sort(sortFunction)来注入自定义函数,但我需要根据外部变量使用不同的函数(在排序过程中是固定的) 我将排序减少到显示问题的最小测试用例,并尝试注入“降序/升序”参数,尽管实际的prolem要复杂得多。我知道我可以扭转结果,但这不是问题 代码如下: var ar = [ 10, 3, 5, 17 ]; var ns = new nsort();

我正在尝试对javascipt中的对象数组进行排序。排序顺序本身取决于两个因素:对象的属性和单个外部变量的值。我知道我可以使用array.sort(sortFunction)来注入自定义函数,但我需要根据外部变量使用不同的函数(在排序过程中是固定的)

我将排序减少到显示问题的最小测试用例,并尝试注入“降序/升序”参数,尽管实际的prolem要复杂得多。我知道我可以扭转结果,但这不是问题

代码如下:

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)

看起来数组排序代码在排序时提取父对象之外的函数

你知道为什么会这样吗?正确的方法是什么

更新:我确实找到了一种方法让它工作:

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;
    }
}

这是个好主意吗?还是有更好的方法?

您的
ns.sort
正在丢失其调用上下文。换句话说,一旦将其传递给
.sort()
,它就不再与
ns
对象有任何连接

您可以让函数直接引用对象,方法是使构造函数中的变量指向该对象,并让排序函数引用该变量

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);
}

您的
ns.sort
正在丢失其调用上下文。换句话说,一旦将其传递给
.sort()
,它就不再与
ns
对象有任何连接

您可以让函数直接引用对象,方法是使构造函数中的变量指向该对象,并让排序函数引用该变量

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);
}

您需要使用
bind
。看


简言之,这表示“使用排序函数
ns.sort
,但是调用它,以便该函数在内部使用
ns
作为
表达式的值。

您需要使用
绑定
。请参阅


简言之,这表示“使用排序函数
ns.sort
,但是调用它,以便该函数在内部使用
ns
作为
表达式的值。

代替
绑定
也可以使用此模式(使用闭包):

为了好玩,这里有一个更简单、更“实用”且避免调用上下文问题的方法:

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 ]

除了
bind
之外,您还可以使用此模式(使用闭包):

为了好玩,这里有一个更简单、更“实用”且避免调用上下文问题的方法:

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 ]

+首先感谢你,并给了我一个很好的解释。我本来打算删除我的答案的,因为你是第一个,但留下了它,因为我们在不同的地方使用了
bind
;我可以简单地使用var desc=true;这有什么缺点吗?@Milanbabškov:一点也没有。这完全取决于你的实际用途。但是如果你这样做了,那么构造函数似乎没有多大用处。事实上,我认为您应该创建两个单独的函数,并在您想要上升或下降时使用它们。正如我所写的,这不仅仅是asc/desc,这只是简化了。实际上,该参数是一个整数,用于某些复杂的if/else规则。因此,不仅有2个函数,还有20多个不同的函数。@Milanbabškov:使用函数工厂创建自定义分类器,其中唯一的区别是您提供的整数。+1表示第一个,并给出了很好的解释。我本来打算删除我的答案的,因为你是第一个,但留下了它,因为我们在不同的地方使用了
bind
;我可以简单地使用var desc=true;这有什么缺点吗?@Milanbabškov:一点也没有。这完全取决于你的实际用途。但是如果你这样做了,那么构造函数似乎没有多大用处。事实上,我认为您应该创建两个单独的函数,并在您想要上升或下降时使用它们。正如我所写的,这不仅仅是asc/desc,这只是简化了。实际上,该参数是一个整数,用于某些复杂的if/else规则。因此,不仅有2个函数,而且还有20多个不同的函数。@Milanbauškov:使用函数工厂创建自定义分类器,其中唯一的区别是您提供的整数。关于您的更新,这是一个有效的解决方案,但与原始方案略有不同。这取决于实际使用情况。如果您只想创建一个升序函数或降序函数,那么我就不需要构造函数了。如果您打算在一个对象上存储其他属性,那么您可能需要一个。对于您来说,“有更好的方法吗?”问题的答案是这取决于。您的更新(以及我的回答)依赖于在排序时明确
的上下文,而代价是复制对
ns
的引用。user1689607可能有一个更好的方法,它说“我的
sort
对象中的sort方法将总是在包含被调用函数的
sort
对象上解释
这个
。“难道你不喜欢这些JavaScript上下文问题吗?:)关于您的更新,这是一个有效的解决方案,但与原来的有点不同。这取决于实际使用情况。如果您只想创建一个升序函数或降序函数,那么我就不需要构造函数了。如果您打算在一个对象上存储其他属性,那么您可能需要一个。对于您来说,“有更好的方法吗?”问题的答案是这取决于。您的更新(以及我的答案)依赖于对