从已定义的函数创建闭包?

时间:2013-02-23 17:38:20

标签: javascript arrays sorting closures

我想扩展Array.sort()以接受另一个参数。 This question有一个使用闭包的解决方案,所以这段代码有效:

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 个答案:

答案 0 :(得分: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);
    }
};

答案 1 :(得分:2)

您当然无法追溯修改myComp1以关闭来自其他范围的本地变量c;这根本不是闭包的工作方式,也不是局部变量的工作原理。您应该首先正确定义myComp1

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

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

myComp1

这非常难看,这意味着这个函数是不可重入的(因为每个调用都会覆盖彼此的调用var wrapped_myComp1 = function (a,b,c) { window.c = c; var ret = myComp1(a,b); delete window.c; return ret; }; ),但它应该可以工作。

答案 2 :(得分:0)

函数问题myComp1是你的函数尝试使用未定义的全局变量c。 在JavaScript函数中有词法范围,而不是函数使用它们定义的范围。只有关闭不足以解决您的问题。尝试在闭包中分配c变量,例如id this code:

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

答案 3 :(得分:0)

这将有效

var c = 'test'
var myComp1 = function(a,b) { console.log(c); return a-b };

arr.sort( myComp1 );

这里的闭包定义了c(但你需要它定义如上,如果你没有定义c,那么你将得到你得到的错误。)