我这些天学习了很多javascript,其中一个我不太了解的事情就是将函数作为参数传递给其他函数.我得到了做这些事情的概念,但我自己无法想出任何理想的情况.
我的问题是:
你想什么时候让你的javascript函数作为参数使用另一个函数?为什么不直接为该函数的返回值赋一个变量,并将该变量传递给函数,如下所示:
// Why not do this
var foo = doStuff(params);
callerFunction(foo);
//instead of this
callerFunction(doStuff);
Run Code Online (Sandbox Code Playgroud)
我很困惑为什么我会选择做第二个例子中的事情.
你为什么要这样做?有哪些用例?
谢谢!!
Ori*_*rds 25
有几个用例:
假设你有很多不同的代码.在每一段代码之前和之后,您都想做其他事情(例如:log或try/catch异常).
你可以编写一个"Wrapper"函数来处理这个问题.例如:
function putYourHeadInTheSand(otherFunc) {
try{
otherFunc();
} catch(e) { } // ignore the error
}
....
putYourHeadInTheSand(function(){
// do something here
});
putYourHeadInTheSand(function(){
// do something else
});
Run Code Online (Sandbox Code Playgroud)
让我们说你以某种方式加载一些数据.您可以在后台加载它,而不是锁定等待它加载的系统,并在结果到达时对结果执行某些操作.
现在你怎么知道什么时候到来?您可以使用类似信号或互斥的东西,这很难编写和丑陋,或者您可以只做一个回调函数.您可以将此回调传递给Loader函数,该函数可以在完成后调用它.
每次你这样做XmlHttpRequest,这都是正在发生的事情.这是一个例子.
function loadStuff(callback) {
// Go off and make an XHR or a web worker or somehow generate some data
var data = ...;
callback(data);
}
loadStuff(function(data){
alert('Now we have the data');
});
Run Code Online (Sandbox Code Playgroud)
这类似于回调,但不是只调用一次回调,而是可以多次调用它.想象一下,您的加载数据功能不只是加载一位数据,也许加载200.
这最终与for/foreach循环非常相似,除了它是异步的.(您不等待数据,它在准备就绪时会调用您).
function forEachData(callback) {
// generate some data in the background with an XHR or web worker
callback(data1);
// generate some more data in the background with an XHR or web worker
callback(data2);
//... etc
}
forEachData(function(data){
alert('Now we have the data'); // this will happen 2 times with different data each time
});
Run Code Online (Sandbox Code Playgroud)
让我们说你的函数用一些文本做了些什么.但它只需要文本中的一次可能是5次,并且加载文本可能非常昂贵.
所以代码看起来像这样
var text = "dsakjlfdsafds"; // imagine we had to calculate lots of expensive things to get this.
var result = processingFunction(text);
Run Code Online (Sandbox Code Playgroud)
处理功能实际上只需要文本的20%!我们浪费了所有这些额外时间加载它的努力.
您可以传递一个生成文本的函数,而不是传递文本,如下所示:
var textLoader = function(){ return "dsakjlfdsafds"; }// imagine we had to calculate lots of expensive things to get this.
var result = processingFunction(textLoader);
Run Code Online (Sandbox Code Playgroud)
你必须改变你processingFunction的期望另一个功能而不是文本,但这真的很小.现在发生的事情是,processingFunction只会调用textLoader它需要的20%的时间.其他80%的时间,它不会调用该功能,你不会浪费所有的努力.
如果你发生了延迟加载,那么该textLoader函数可以在结果文本获得后私下将结果文本存储在变量中.有人第二次调用它textLoader,它可以返回该变量并避免昂贵的计算工作.
调用的代码textLoader不知道或不关心数据是否被缓存,它透明地更快.
通过传递函数可以做很多更高级的事情,这只是表面上的问题,但希望它指出你正确的方向:-)
最常见的用法之一是作为回调.例如,使用一个函数对数组中的每个项运行一个函数,并将结果重新分配给数组项.这要求函数为每个项调用用户的函数,除非传递函数,否则这是不可能的.
这是这样一个函数的代码:
function map(arr, func) {
for (var i = 0; i < arr.length; ++i) {
arr[i] = func(arr[i]);
}
}
Run Code Online (Sandbox Code Playgroud)
用法的一个例子是将数组中的每个项乘以2:
var numbers = [1, 2, 3, 4, 5];
map(numbers, function(v) {
return v * 2;
});
// numbers now contains 2, 4, 6, 8, 10
Run Code Online (Sandbox Code Playgroud)
如果callerFunction想doStuff稍后打电话,或者想要多次打电话,你会这样做.
这种用法的典型示例是回调函数,您将回调函数传递给函数jQuery.ajax,然后在完成某些操作时调用您的回调(例如AJAX请求)
编辑:回答你的评论:
function callFiveTimes(func) {
for(var i = 0; i < 5; i++) {
func(i);
}
}
callFiveTimes(alert); //Alerts numbers 0 through 4
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12109 次 |
| 最近记录: |