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首先正确定义。

但如果你不能这样做,那么有一种解决方案。

因为myComp1引用 ac不是范围的局部变量,所以它真正引用的是全局变量c;也就是说,它引用'c'全局对象上命名的属性(window如果主机是 Web 浏览器)。所以你可以做的是,你可以创建一个包装函数,将一个局部变量复制到全局对象上,然后调用myComp1; 像这样的东西:

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 中,函数具有词法范围,这意味着函数使用定义它们的范围。而且只有关闭不足以解决您的问题。尝试在闭包中分配 c 变量,如 id 这段代码:

 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 回答