22

有时我会看到 JavaScript 是用一个提供的参数编写的,该参数已经有一个设定值或者是一个带有方法的对象。以这个 jQuery 示例为例:

$(".selector").children().each(function(i) {
    console.log(i);
});

当 logging时,当查看 jQuery方法中的选择器子项时i,您将获得该迭代中任何内容的值。ieach

以这个 Node.js 为例:

http.createServer(function(request, response) {
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
}).listen(8888);

你可以在这里看到request并且response正在被传递,它们包含自己的可以被执行的方法。

对我来说,这看起来像是将一个函数传递给createServer带有两个已附加方法的参数的函数。

我的问题是多部分的:

  1. 这些论据从何而来?
  2. 如果这些只是匿名函数,它们如何接收可以像其他函数一样起作用的参数?
  3. 我如何创建可以像这样接受我自己的参数的函数?
  4. 这是否使用了闭包的力量?
4

5 回答 5

19

对我来说,这看起来像是将一个函数传递给 createServer 函数,其中两个参数已经附加了方法。

不,他们正在传递一个createServer需要两个参数的函数。稍后将使用调用者输入的任何参数调用这些函数。例如:

function caller(otherFunction) {
     otherFunction(2);
 }
caller(function(x) {
    console.log(x); 
});

将打印 2。

更高级的是,如果这不是您想要的,您可以使用属于所有函数的bind方法,这将创建一个已绑定指定参数的新函数。例如:

caller(function(x) {
    console.log(x);
}.bind(null, 3);
});

现在将打印 3,传递给匿名函数的参数 2 将成为未使用且未命名的参数。

无论如何,这是一个密集的例子;请查看链接文档bind以了解绑定如何更好地工作。

于 2013-08-12T20:09:40.570 回答
4

让我们看一下$.each这个例子:

each: function (obj, callback, args) {
    var value,
    i = 0,
        length = obj.length,
        isArray = isArraylike(obj);

    if (args) {
        if (isArray) {
            for (; i < length; i++) {
                value = callback.apply(obj[i], args);

                if (value === false) {
                    break;
                }
            }
        } else {
            for (i in obj) {
                value = callback.apply(obj[i], args);

                if (value === false) {
                    break;
                }
            }
        }

        // A special, fast, case for the most common use of each
    } else {
        if (isArray) {
            for (; i < length; i++) {
                value = callback.call(obj[i], i, obj[i]);

                if (value === false) {
                    break;
                }
            }
        } else {
            for (i in obj) {
                value = callback.call(obj[i], i, obj[i]);

                if (value === false) {
                    break;
                }
            }
        }
    }

    return obj;
}

这被称为

$(".selector").children().each(function(i) {
    console.log(i);
});

喜欢:

return $.each.call(this, callback /* this is your function */, args /* which is an additional thing people rarely use*/ )

这是您要查看的行(在第一个块中)

callback.call(obj[i], i, obj[i]);

它调用回调,并将对象作为上下文传递——这就是你可以this在循环中使用的原因。然后迭代i和与上下文相同的对象都作为参数发送给回调。这有点像魔术。直到你查看源代码。

于 2013-08-12T20:12:34.700 回答
1

这是将参数传递给匿名函数的示例

    var a = 'hello';

    // Crockford
    (function(a){alert(a)}(a));

    // Others
    (function(a){alert(a)})(a);

它使用闭包,因为它是一个匿名函数(这实际上完全取决于你如何编写它)

于 2014-05-27T15:19:06.613 回答
0

如果您查看 createServer 的代码,它看起来像这样:

function createServer (handleRequestAndResponseFunction) {
    handleRequestAndResponseFunction(actualRequest, actualReponse);
}

好的,不,它不会,但这是一个简单的例子。createServer 接受一个function接受两个参数的 a。

在更现实的情况下,当您传入具有两个参数的函数时,它会执行任何中间件处理和它需要的东西,然后调用该函数,传递它自己的请求和响应变量。

于 2013-08-12T20:17:55.467 回答
0

是的,您将函数作为参数传递。您传递的函数当然会有自己的参数。

而且,这些参数可以是任何东西,包括可能有自己的方法的对象等。

http.createServer将接受一个函数,它会知道该函数有多少参数。一种方法是检查arguments传入函数的属性。或者 api 开发人员可能已经使用了实际的元素。

此函数的编写者将知道参数的预期内容,并将其记录在api documentation.

于 2013-08-12T20:08:17.017 回答