这些天我学习了很多javascript,其中一个我不太了解的事情是将函数作为参数传递给其他函数。我得到了做这些事情的概念,但我自己无法想出任何理想的情况。
我的问题是:
您希望何时使用其他函数作为参数?为什么不直接为该函数的返回值赋值,并将该变量传递给函数,如下所示:
// Why not do this
var foo = doStuff(params);
callerFunction(foo);
//instead of this
callerFunction(doStuff);
我很困惑为什么我会像第二个例子那样选择做事。
你为什么要这样做?有哪些用例?
答案 0 :(得分:3)
处理程序/听众就是一个很好的例子。
更一般地说,当你不知道g是否需要调用f,调用它需要多少次,和/或使用哪些参数时,你可以将函数f作为参数传递给函数g。
示例:
答案 1 :(得分:3)
这是另一个例子。对数组进行一些格式化操作:
function pctFormatter(num) {
return num + '%';
}
function centsFormatter(num) {
return num + '.00';
}
function formatThisArray(array, formatter) {
var output = [];
for(var i = 0; i < array.length; i++) {
output.push( formatter(array[i]) );
}
return output;
}
formatThisArray([1,2,3], pctFormatter);// returns ['1%', '2%', '3%']
formatThisArray([1,2,3], centsFormatter);// returns ['1.00', '2.00', '3.00']
答案 2 :(得分:2)
如果您没有通过params
,而callerFunction()
会通过,则会执行此操作。
对AJAX请求的回调是一个用例。
function myCallback(response) {
// do something with the response
}
myAJAX('http://example.com/foo.json', myCallback)
这使myAJAX
能够完成请求并等待响应。然后它调用myCallback
并在响应最终到达时将响应传递给它。
答案 3 :(得分:1)
// Why not do this
var foo = doStuff(params);
callerFunction(foo);
//instead of this
callerFunction(doStuff);
第一个示例将使用doStuff
运行函数params
,并将结果分配给foo
。将使用参数callerFunction
(现在是foo
的结果)调用dooStuff
;
第二个示例将调用callerFunction
并将doStuff
作为参数传递。 callerFunction
可能会也可能不会调用doStuff
。
答案 4 :(得分:1)
好吧,有时你不知道函数的调用者是谁,直到它被调用 - 这排除了传递预先计算的值。
我想到的几个例子是:
(a)setTimeout或setInterval - 您希望在指定时间段(一次性或重复次数)后调用特定函数。如果调用的函数返回了一个依赖于时间的值,则有些情况下您无法预先计算该值 - 它需要在计划的时间完成。因此,我们告诉函数在指定的时间调用我们自己的函数。
(b)在加载(或至少加入)各种资源时。我们可以为元素提供一个在加载成功时执行的函数,以及另一个在失败时执行的函数。在调用这两个(用户提供的)函数之一之前,您实际上并不知道加载资源的工作何时完成。在许多资源的情况下,您可以在此处增加计数器,以保持成功/失败的加载尝试次数。
(c)通过调用getElementsByClass或getElementsByTagName返回的NodeList。它不是一个实际的(javascript本机)Array对象。因此,您不能像使用数组一样调用forEach方法。为了解决这个问题,我使用了以下辅助函数:
// getElementsByTagName, getElementsByClass - both return a NodeList
// it is accessed in the same way as an array - with the [] operators, but it's
// not an array object - this is a function that allows us to still iterate through it
// in much the same way.
function forEachNode(nodeList, func)
{
var i, n = nodeList.length;
for (i=0; i<n; i++)
{
func(nodeList[i], i, nodeList);
}
}
这允许我获取节点列表,然后在每个节点上调用一些用户定义的函数。在使用中,它看起来像这样:
var allAnchors = document.getElementsByTagName('a');
forEachNode(allAnchors, showNodeTextVal);
function showNodeTextVal(curElem, curIndex, origList)
{
alert(curElem.innerText);
}
或更简单:
var allAnchors = document.getElementsByTagName('a');
forEachNode(allAnchors, function(curElem){alert(curElem.innerText);} );
与不使用此辅助函数时相比,这是一个更清晰,更不容易出错的情况。为了实现相同的功能,我们需要编写以下代码:
var nodeList = document.getElementsByTagName('a');
var i, n = nodeList.length;
for (i=0; i<n; i++)
{
alert(nodeList[i].innerText);
}
答案 5 :(得分:0)
最常见的情况是JQuery中的处理程序:
function clickHandler(e){
// handle click on e.Target
}
$("#button").click(clickHandler);
$(function(){
// do ready state initialization
});
答案 6 :(得分:0)
callerFunction(doStuff);
使用此代码,您可以向函数doStuff
callerFunction
的“指针”
你可以像这样使用它:
function callerFunction(doStuff) {
var x = doStuff(...);
...;
}
您可以在函数中使用函数,而不仅仅是doStuff
的返回值。
问候!
答案 7 :(得分:0)
你想什么时候让你的javascript函数拿另一个 作为参数?
它对回调非常有用,例如:
function add( a, b, callback ) {
callback( a, b );
return a + b;
}
function added( a, b ) {
alert('You just added two numbers: '+ a +' and '+ b);
}
alert( add( 1, 2, added ); // Will alert the message and then the result.
这是一个非常简单的示例,但是非常对异步函数有用,因此您可以在完成后运行代码而不会中断脚本。
答案 8 :(得分:0)
当你想让你的代码真正将函数作为函数处理时,你需要传递函数本身而不是返回值 - 要执行的代码。考虑这个伪代码示例:
function saveToLocalStorage(data) {...//saves to local storage}
function saveToServer(data) {...//saves via AJAX to server}
function saveToAmazonS3(data) {.../saves to Amazon S3 }
function multiSave(data, saverFunctions) {
saverFunctions.forEach(function (saverFunction) {
saverFunction(data);
});
}
multiSave({user: "tim"}, [saveToLocalStorage, saveToServer, saveToAmazonS3]);
在这种情况下,我希望传递实际函数本身,并希望其他代码稍后调用它们。当我们这样做时,multiSave
之类的函数被称为高阶函数,因为它直接处理其他函数。由于multiSave的工作方式,我可以轻松地在本地/服务器/ S3旁边的UI中放置一些复选框,并允许用户选择数据的位置,如果我无法将函数传递给参数。
答案 9 :(得分:0)
当你将一个函数作为参数传递时,该参数不是该函数的返回值,但它是函数本身,你可以随意调用它,任何一个你喜欢的论点,或者你可以将它分配给一个事件。
你说你想要一些实际的用例,这里有一个非常常见的情况的简短列表,都要求函数作为参数传递。
让我们看一下你的普通jQuery代码,并计算一个函数作为参数传递的次数:
$(document).ready(function()//<-- 1
{
$('#foo').on('click',function()//2
{
});
$.each(something,function()//3
{});
//and so on
});
如果您不使用jQuery,请尝试事件委派
document.body.addEventListener('click',function(e)
{
e = e || window.event
console.log('This function was passed as an argument to the addEventListener method');
},false);
甚至是简单的Array.prototype.sort
函数(/ method):
anArray.sort(function(a,b)
{
return (a > b ? 1 : -1);
});
或者,如果您需要进行ajax调用,而不是在现场创建新的XMLHttpRequest
对象,您可能需要一个单独的函数来设置xhr对象,并传递url,data < em>和onreadystatechange
回调作为参数:
function makeXHR(url,data,callback)
{
try
{
var xhr = new XMLHttpRequest();
}
catch(e)
{
//etc...
}
xhr.onreadystatechange = callback;
}
makeXHR('some/url','foo=bar',function()
{
if (this.readyState === 4 && this.status === 200)
{
//do stuff
}
});
在所有这些例子中,我已经在线创建了这些函数,当然引用一个函数(通过传递它的名字)也可以正常工作:
makeXHR('some/url','foo=bar',defaultXhrCallback);
这些只是成千上万的用例中你可以/必须将函数作为参数传递给另一个函数