为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
作为this
expression式的值。
而不是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 ]