【发布时间】:2016-04-25 17:49:55
【问题描述】:
问题和疑问
我有一个小型应用程序,它从服务器异步获取 JSON 数据,将其格式化为表格,并允许用户对表格执行一些简单的操作(排序、过滤等)。
其中一个排序函数访问先前生成的表中的 DOM 元素(定义如下)。
var SORT = function(){
var my = {};
// public methods
my.byName = function(sign){
(!sign) ? sign=1 : 1;
var T = $("#resultArea").find("tbody");
var R = T.children("tr");
R.sort( function(a,b){
var an = $(a).attr("data-name");
var bn = $(b).attr("data-name");
return sign * an.localeCompare(bn);
});
R.detach().appendTo(T);
}
...
return my; }();
当将它指定为用户可以点击的元素的回调时,我有两个公式。
$("#sort-button").click(SORT.byName);(将函数作为参数传递)
或
$("sort-button").click(function(){SORT.byName();});(传递调用函数的匿名闭包)
第一个选项失败,但第二个有效。以下是它在要排序的 536 行的测试用例中失败的原因:
- 前第 2 行(按字母顺序位于第 1 行之前)移至位置 268。
- 之前的第 269 行移动到位置 536。
- 前行 536 移动到位置 2。
我尝试过构建一个以相同方式失败的 MWE,但失败了(一旦我成功就会更新问题)。问题是:出了什么问题?为什么使用匿名闭包有效?
更新
sn-p 的早期版本已被清理以删除参数 sign 和开头的行(如果它评估为 false 或未定义,则会将符号设置为 1),其想法是通过传递sign=-1 作为参数,可以进行降序排序。当我从实时代码的定义中删除 sign 时,问题就消失了。
所以我发现有问题的行是(!sign) ? sign=1 : 1;,当替换为更透明的if(sign !== undefined){sign=1;} 时,问题就消失了。我认为它的作用是在第一次通过时将 global sign 设置为一个,然后在第二次通过时,将符号定义为 返回 1,函数结束(只完成了一次)。
那为什么这个错误不会使匿名闭包方法上的排序崩溃?
【问题讨论】:
-
鉴于
byName没有在任何地方使用this也没有接受任何参数,所以应该没有任何可观察到的差异。 -
SORT对象是在您附加点击处理程序之前创建的,之后就再也没有改变过,对吧? -
@Bergi 正确。 SORT 定义一次,并带有一些在某些用户事件上调用的方法。仍然无法重现该错误。数字排序和字母排序都会出现相同的故障模式。
-
@Bergi 实际上,您的第一条评论让我意识到我在清理要发布的代码时遗漏了一个细节……我删除了一个我认为不相关的参数。现在将更新问题。
标签: javascript sorting scope closures