将JavaScript函数设置为与其他函数一起使用的参数?

时间:2012-11-06 22:47:12

标签: javascript

这些天我学习了很多javascript,其中一个我不太了解的事情是将函数作为参数传递给其他函数。我得到了做这些事情的概念,但我自己无法想出任何理想的情况。

我的问题是:

您希望何时使用其他函数作为参数?为什么不直接为该函数的返回值赋值,并将该变量传递给函数,如下所示:

// Why not do this
var foo = doStuff(params);
callerFunction(foo);

//instead of this
callerFunction(doStuff);

我很困惑为什么我会像第二个例子那样选择做事。

你为什么要这样做?有哪些用例?

10 个答案:

答案 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);

这些只是成千上万的用例中你可以/必须将函数作为参数传递给另一个函数