jQuery: 什么是“值回调”?

7
我正在学习《学习jQuery》(第三版)。
在第四章“操作DOM”中,有一个解释叫做“值回调”的部分。这对我来说是新的。
作者通过一个链接列表的例子来解释这个概念,其中每个ID都必须是唯一的。
从书中可以看到:
“值回调只是一个函数,它被提供给参数代替值。然后,该函数会针对匹配集合中的每个元素调用一次。从函数返回的任何数据都将用作属性的新值。例如,我们可以使用这种技术为每个元素生成不同的id值,如下所示:”
Chaffer, Jonathan (2011-09-23). Learning jQuery, Third Edition (p. 116). Packt Publishing. Kindle Edition.
jQuery(document).ready(function($){

// get all external links
   $('div.chapter a').attr({
        rel:'external',
        title:'Learn more at Wikipedia',
        id: function ( index, oldValue ) {
                return 'wikilink-' + index;
        }
    });
})

这个功能非常好用,但是我对id属性的机制还不太理解。

  1. 第一参数(索引)如何知道它是一个整数?
  2. 函数如何知道要将索引递增?
  3. 第二个参数(oldValue)如何知道要保存属性的旧值(在修改之前)?
  4. 这是jQuery的构造吗?JSON的东西?这很酷,它能工作,但是…这个"value callback"到底是什么?

请指教。

2个回答

6

1) 参数1(索引)如何知道是整数?

jQuery传递一个整数。

2) 函数如何知道要增加索引?

回调函数不会增加index,jQuery方法会。

3) 第二个参数(oldValue)如何知道属性的旧值(修改前)?

jQuery将其传递。

对于问题1-3的答案,最好理解的方式可能是执行类似于$.attr的函数:

Array.prototype.each = function (f) {
    var i;
    for (i=0; i < this.length; ++i) {
        f(i, this[i]);
    }
};

['zero', 'one', 'two'].each(function (i,item) {console.log({i: item})});

f是一个回调函数。each负责遍历集合并为每个索引和项调用f。相同的代码结构可以用于函数:

/* Map each item in a sequence to something else, 
 * returning a new sequence of the new values.
 */
Array.prototype.map = function (f) {
    var i, result = [];
    for (i=0; i < this.length; ++i) {
        result[i] = f(i, this[i]);
    }
    return result;
};

['zero', 'one', 'two'].map(function(i,item) {return item.length});
// result: [4, 3, 3]

/* Return a sequence of the items from this sequence 
 * for which 'keep' returns true.
 */
Array.prototype.filter = function (keep) {
    var i, result = [];
    for (i=0; i < this.length; ++i) {
        if (keep(i, this[i])) {
            result.push(this[i]);
        }
    }
    return result;
};

['zero', 'one', 'two'].filter(function(i,item) {return item.length <= 3});
// result: ['one', 'two']

实现mapconcatfoldlfoldr需要自己完成。另一个练习是使用each重写mapfilter

请注意,这些函数仅旨在说明回调的工作原理。它们可能会在生产代码中引起问题。

4) 这是jQuery构造吗?JSON的东西?很酷。它能用,但是……这个“值回调”到底是什么?

回调函数是jQuery广泛使用的一种通用技术。它们是函数式编程的关键特征,其中函数是可以像其他数据类型一样进行操作的数据。因此,您可以有将函数作为参数并能够返回函数的函数。在某些情况下,回调函数也被称为“continuations”,并构成了continuation passing styleCPS)的基础。这对于异步函数调用 [2](函数在计算完成之前返回,而不是同步调用)尤其重要,例如用于Ajax请求。要了解CPS的一些强大功能,请阅读{{link9:“使用continuations开发复杂的Web应用程序”}}。

这里提到的“value callback”中的“value”是指,由于JS是一种动态类型语言(类型与数据相关联,而不是变量),因此形式参数可以绑定到任何类型的对象上。函数的行为取决于传递的内容。有时候会通过检查参数类型来实现这一点,这实际上是临时多态(函数必须处理分发,而非语言)。然而,参数多态或者(如果失败)鸭子类型应该始终优先于检查参数类型。参数多态可以通过确保所有可以传递给给定函数的类型都支持相同的接口(方法名称、参数、前置条件、后置条件等)来实现。例如,所有序列类型都应该有一个length属性,并且可以通过整数进行索引;只要满足这个条件,你就可以使用自己的序列类型和许多需要数组的函数。
我不确定你所说的 JSON 是什么意思,但它可能并不是常见的那种。JSON 是一种基于 JS 对象字面语法的受限数据交换格式。JSON 在示例代码或引用文本中没有任何涉及。

更好的解释!我现在“懂了”。所以这个模式根本不是柯里化的例子? - sleeper
对于柯里化的讨论对我来说仍然很新,超出了我的理解范围。但是,你的阐述完全回答并解释了我提出的问题。因此,我已经把我的答案选择转为了你的。感谢你在这个答案中付出的所有努力! - sleeper

4

这是一个 JQuery 的结构。如果您查看源代码,您会发现 JQuery 正在检查参数以了解您是否传递了一个值或一个函数。如果它是一个函数,它将根据您的使用进行处理。


哇,非常酷。你能推荐一些关于这个主题的进一步阅读吗? - sleeper
实际上,$.attr 没有使用柯里化。柯里化是将一个 n 元函数(接受 n 个参数的函数)转换为 n 个一元函数,其中每个函数(除了最后一个函数)返回一个一元函数。 - outis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接