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

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

我把sorting减less到了最小的testing用例,它显示了问题并试图注入“降/升”参数,尽pipe真正的问题要复杂得多。 我知道我可以扭转()的结果,但这不是一个问题。

代码如下:

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 ba; else return ab; } } 

这里是输出(使用Node.js)

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

它看起来像数组sorting代码在sorting时提取父对象之外的function。

任何想法为什么会发生这种情况,以什么方式来做到这一点?

更新:我find了一种方法来使其工作:

 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 ba; else return ab; } } 

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

你的ns.sort正在失去它的调用上下文。 换句话说,一旦你把它传递给.sort() ,它不再有任何连接到ns对象。

您可以让函数直接引用对象,方法是在构造函数中指向一个variables,然后让sorting函数引用该variables。

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

或者,如果您处于像NodeJS这样的现代环境中,则可以使用Function.prototype.bind()永久地将调用上下文值附加到该函数。

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

你需要使用bind 。 请参阅http://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 ba; else return ab; } } 

简而言之,这说“使用sorting函数ns.sort但调用它,以便内部该函数使用ns作为thisexpression式的值。

而不是bind你也可以使用这个模式(使用闭包):

 function nsort(desc) { desc = desc || false; this.setDesc = function(val){desc = val; return this;} this.sort = function(a,b) { return desc ? ba : ab; } } 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”,并避免调用上下文问题:

 function nsort(desc) { return function(a,b){ return desc ? ba : ab; }; } 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 ]