正如 OP 所指出的,while 条件之后没有语句。注意 while 循环后面的分号,return this 仅在 while 循环完成后运行,即当三个语句中的任何一个评估为 false 时。如果您只想知道 while 循环是如何工作的,Filip Bartuzi 的回答可能是最完整的。我将尝试就each2 方法的作用给出更广泛的答案。
如文档中所述,它只是专为 select2 使用而设计的 jQuery's #each、Array.prototype.forEach、Underscore's #each 或 lodash's #forEach 的更高效版本。它用于迭代任何数组或其他可迭代对象,包装在 jQuery 对象中。所以它用于字符串数组以及 jQuery 集合。
它的工作方式是作用域 (this) 是调用它的数组。它被赋予一个函数作为参数。这正是我之前提到的其他each 方法的调用方式。为数组中的每个项目调用一次提供给each2 的函数。 while 循环是一种遍历数组中每个项目并调用函数的方法,将项目设置为上下文并将数组中的索引和项目作为 jQuery 对象作为第一个和第二个参数传递。必须评估while 循环条件中的每个语句以确定它是否为真,并且该过程用于实际为变量赋值,并递增i。 c.call(j[0], i, j) !== false 部分允许函数通过返回 false 提前终止循环。如果函数返回 false,while 循环将停止,否则将继续执行,直到 i 大于 l,这意味着数组中的每一项都已被使用。之后返回 this 只会使另一个方法链接到 .each2 之后的数组。
基本上while 循环可以重写为:
var j = $([0]), i = 0, l = this.length, continue = true;
while (i < l) {
i++;
j.context = j[0] = this[i];
continue = c.call(j[0], i, j);
if (!continue) {
break;
}
}
但可能有一些性能原因导致浏览器无法对其进行优化。
它比普通的each 方法更脆弱。例如,如果数组中的某个元素具有错误值,例如0,则(j.context = j[0] = this[i]) 将是错误的,从而导致循环终止。但它只用于 select2 代码的特殊情况,不应该发生这种情况。
让我们看几个例子。
function syncCssClasses(dest, src, adapter) {
var classes, replacements = [], adapted;
classes = $.trim(dest.attr("class"));
if (classes) {
classes = '' + classes; // for IE which returns object
$(classes.split(/\s+/)).each2(function() {
if (this.indexOf("select2-") === 0) {
replacements.push(this);
}
});
}
...
^ 此代码从dest DOM 元素中获取类。这些类被分割成一个字符串数组(字符串被分割成空白字符,即\s+ 正则表达式),每个类名都是数组中的一个项目。这里不需要特殊的 jQuery 工作,因此不使用 each2 调用的函数提供的 2 个参数。如果该类以“select2-”开头,则该类被添加到名为replacements 的数组中。 'select2-' 类正在被复制,非常简单。
group.children=[];
$(datum.children).each2(function(i, childDatum) { process(childDatum, group.children); });
^ 为简洁起见,我没有包含此方法的其余部分,但它是 process 方法的一部分。在这种情况下,each2 用于递归地process 一个节点及其所有子节点。 $(datum.children) 是一个 jQuery 选择,每个 'child'(命名为 childDatum)都会被依次处理,它的孩子也会经历同样的过程。 group.children 数组将用作一个集合,为每个 childDatum 添加到该数组的任何内容都将可用,因此在运行 each2 之后,它将保存在处理所有子进程期间添加的所有内容,孙子等等。