问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

js中什么是回调函数

发布网友 发布时间:2022-04-24 10:19

我来回答

2个回答

懂视网 时间:2022-05-14 15:00

平常的前端开发工作中,编写js时会有很多地方用到函数的回调。

最简单的例子就是:

<script language="javascript" type="text/javascript">
function doSomething(callback) {
if(typeof callback == "function") {
callback();
}
} 
 
function foo() {
alert("我是回调后执行的函数");
} 
 
doSomething(foo); /*正确*/
doSomething(function(){
alert("我是回调后执行的函数");
}); /*正确*/
doSomething("foo"); /* 这样是不行的,传入的是一个字符串,不是一个函数名 */
</script>

以上只能回调没有参数的(除法你事先知道回调的函数的参数),如果函数有未知的函数,就不能如此简单的调用了。

高级方法:

1、使用javascript的call方法

function doSomething(callback,arg1,arg2) {
callback.call(this,arg1,arg2);
}
function foo(arg1,arg2) {
alert(arg1+":"+arg2);
}
doSomething(foo,1,2); /* 弹出了1:2 */

2、使用javascript 的 apply方法

function doSomething(callback,args) {
callback.apply(window,args);
}
function foo(arg1,arg2) {
alert(arg1+":"+arg2);
}
doSomething(foo,[1,2,3]); /* 弹出了1:2 */

可以看成call和apply基本一样,区别就是call只能一个个传参数,apply只能把参数放数组里传进来。

他们的第一个参数都是作用域,比如上面传了this,表示就是和doSomething这个函数一样的作用域,当然你也可以传window,表示整个window的作用域。

3、apply的巧妙用法

apply也可以看作是函数的执行函数,就是用来执行某个函数的函数。所以你会发现,有时候用好apply,有很多原本繁杂的事情会变得如此简单。

比如数组的push方法使用apply来调用:

var arr1=[1,3,4];

var arr2=[3,4,5];

如果我们要把 arr2展开,然后一个一个追加到arr1中去,最后让arr1=[1,3,4,3,4,5]

arr1.push(arr2)显然是不行的。 因为这样做会得到[1,3,4,[3,4,5]]

我们只能用一个循环去一个一个的push(当然也可以用arr1.concat(arr2),但是concat方法并不改变arr1本身)

var arrLen=arr2.length
for(var i=0;i<arrLen;i++){
 arr1.push(arr2[i]);
}

自从有了Apply,事情就变得如此简单

Array.prototype.push.apply(arr1,arr2)

一行代码就解决了,原理能看的出来,Array.prototype.push是指数组的push函数,apply(arr1,arr2)说明arr1是作用域,就等同于是arr1调用了数组的push函数,

而且arr1的确就是个数组,所以可以调用,arr2表示入参的数组。所以,以上语句等同于:arr1.push(3,4,5)。(push函数支持传递多个入参,这也是这里可以使用apply的前提条件)

以上语句也可以写成:arr1.push.apply(arr1,arr2); 两者完全等效,因为arr1.push表示arr1的push函数,也就是数组的push函数。

如果使用call就是这样Array.prototype.push.call(arr1,arr2[0],arr2[1]...),显然还是apply合适。

要是你还问,那直接用arr1.push(3,4,5)不就行了,那已经暴露了你的智商,arr2又不是不可以变,下次不是[3,4,5]了呢。

还有获取数组中,最大的那个数字,也可以使用apply调用Math.max函数

var arr1=[1,3,4];

alert(Math.max.apply(window,arr1)); /* 作用域可以不是window,就算是null都行,Math.max.apply(this,arr1),Math.max.apply(null,arr1) */

4、工作中函数回调的实际例子

有了上面的基础,就能看的懂工作中封装好的js的回调函数了

背景:页面A需要使用页面B来选择某个项目,然后带回这个项目的信息给页面A,页面A根据这些信息丰富自己。

页面A:

noticeInfo = {
selectProject: function () {
var win = newsee.ui.window
win.show('项目列表', '../Project/ProjectSelectList.html?callback=noticeInfo.setProjectInfo', { size: win.winSizeType.big })
//在当前页面弹出框,框里面是另一个页面,地址后面带上需要回调的函数名
//注意这两个页面其实都是在一个页面里面的,并不是像window.open()那样出现了新窗口,所以两个页面的js都是可见的
},
setProjectInfo: function (obj) {
//回调函数,将选择好的项目对象传进来,然后丰富自己的页面
$('#projectName').val(obj.name)
$('#projectID').val(obj.id)
}
}

页面B:

function SelectBack() {
var callback = newsee.util.url.getQuery('callback'); //获取页面参数callback,这里获取到的是"noticeInfo.setProjectInfo",是个字符串
var arr = newsee.ui.grid.getSelectedBack('datagrid') //获取选择的项目,这个不用深究
if (!arr.length) {
return newsee.ui.window.alert('请选择项目!')
}
newsee.util.url.back(callback, arr[0]) //重点来了,这里执行回调,将需要回调的函数名和入参传进来,arr[0]就是选择的项目的对象的数组了(它也是个数组,里面就一个对象)
}

newsee.util.url.back函数如下:

back : function (funcName) {
// / <param name="funcName" type="String">返回时执行的方法,一般为重新绑定</param>
 
var isWindow = typeof $$winClose === 'function',// 是否为弹窗
args // 弹窗返回方法参数
 
if (isWindow) {// 弹窗的返回方法
$$winClose()
 
args = [].slice.call(arguments) //arguments大家应该都知道的吧,它可以用来获取函数的实参,它类似数组又不是数组,这句代码就是把它转换成数组,因为apply的入参需要是个数组才行
//args现在里面有两个元素,args[0]=callback,就是之前传进来的回调函数名,args[1]=arr[0],就是回调函数的入参
newsee.callFunc.apply(newsee, args) //执行 newsee.callFunc 函数,作用域就是newsee自己(等同于newsee自己调用callFunc函数),参数是args
} 
}

newsee.callFunc函数如下:

callFunc: function(funcName, arg) {
var func = typeof funcName === 'function' ? funcName : this.findItem(window, funcName) //上面我有提到过,doSomething("foo"); 传入的是一个字符串,不是一个函数名,所以无法执行
//同样的道理,现在funcName=args[0]=callback="noticeInfo.setProjectInfo",是个字符串,不能直接调用apply,需要变成函数
//这句话就是用来判断funcName是不是一个函数,如果不是,就在window作用域里根据funcName找到这个函数,然后赋给func
if (typeof func === 'function') {
//此时func已经是个函数了,就是页面A里定义的noticeInfo.setProjectInfo()
try {
return func.apply(window, arg) //执行需回调的函数,作用域依然是window,反正这个函数在window里肯定能找到,参数就是arg=args[1]=arr[0],即之前在页面B获取到的项目对象
}
catch (e) {
console.error(e)
}
}
}

ok,需回调的函数就这样被执行了,至于怎么根据字符串形式的函数名获取这个函数,看下面。

//findItem函数如下:
findItem: function(data, key) {
// / <summary>获取对象指定键的值</summary>
if (this.include(data, key)) { //data这里就是传进来的window,注意window就是一个对象,首先判断window对象里是否存在"noticeInfo.setProjectInfo"这个属性
return eval('data.' + key) //如果存在,就执行"data.noticeInfo.setProjectInfo",这样就获取到了这个函数了。(eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码)
}
}
//include函数如下:
include: function(data, key) {
// / <summary>判断对象是否存在键值</summary>
if (data == null || typeof data !== 'object' || !key || typeof key !== 'string') {
return false
}
var keys = key.split('.'),
item = data,
result = true
keys.forEach(function(k) {
if (item != null && typeof item === 'object' && k in item) {
//依次循环遍历,第一次item = data,那就是window这个对象,k="noticeInfo",window[noticeInfo]是存在的,因为在页面A里定义了noticeInfo这么一个对象
//第二次循环,item=window.noticeInfo,k="setProjectInfo",window.noticeInfo[setProjectInfo]也是存在的,因为在页面A里也定义了setProjectInfo这么一个函数
//这里没有第三次循环了,所以最后返回是true,说明window对象里存在"noticeInfo.setProjectInfo"这个属性,接下来使用eval()拿到它即可
item = item[k]
} else {
return result = false
}
})
 
return result
}

对eval() 函数也介绍一下:

eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。

返回值就是通过计算 string 得到的值(如果有的话)。如:

eval("x=10;y=20;document.write(x*y)") //
输出 200 document.write(eval("2+2")) //输出 4 var x=10 document.write(eval(x+17)) //输出 27

所以上面的eval('data.' + key)就是执行"data.noticeInfo.setProjectInfo"这个字符串,

因为data在这里就是指window,所以返回值就是window.noticeInfo.setProjectInfo()这个函数

其实可以在简单一点,根本没必要使用eval()来获取这个函数,因为在include函数里,item就已经是window.noticeInfo.setProjectInfo这个对象了,这个对象就是我们想要的函数。

(在js中函数也是对象,函数名就是这个函数的引用,就和地址差不多)

既然都拿到这个函数了,直接返回不就行了,所以上面的include()和findItem可以这样简化:

include: function(data, key) {
if (data == null || typeof data !== 'object' || !key || typeof key !== 'string') {
}else{
var keys = key.split('.'),
item = data,
result = true
keys.forEach(function(k) {
if (item != null && typeof item === 'object' && k in item) {
item = item[k]
} else {
result = false;
}
})
if(result)
return item
}
},
findItem: function(data, key) {
return this.include(data, key)

经过测试,发现这两个根据字符串形式的函数名获取函数的方法都可以达到一模一样的效果。

热心网友 时间:2022-05-14 12:08

在计算机程序设计中,回调函数,或简称回调,是指通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。
jscallback

1、js中callback简介:一个被当做参数的函数,即为回调函数。在JS中万物皆为对象。函数本身也是一个对象,既然是对象,所以函数当然可以当做函数的参数。如上述代码,fun函数就是一个对象。上述代码中,fun2做为fun1的参数,fun2即为回调函数。2、回调函数的作用几乎所有的第三方函数我们都无法修改函数的...

JS中 success: function ()设置参数上啥意思?看不懂。

success: function ()是回调函数,是一个function方法,需要参数,可以传过来,不需要参数,直接写方法就行了

nodejs里的cb是什么意思

cb的在js中是call-back 也就是回调函数的缩写。call-back function 缩写为cb

jsfind返回默认值

jsfind返回默认值x。jsfind参数为回调函数,回调函数可以接收3个参数,值x,索引i,数组arr,糊掉函数默认返回值x,先确定方法要传入的参数和返回的值,再通过原型定义,在Array的原型上添加自定的方法,验证是否达到预期效果。

...为什么要用callback传函数, 而不直接在这个函数里调用另一个函数_百...

通俗的讲就是被调用的函数不知道你要做什么, 你需要将执行的操作作为回调函数传入 比如插件, 当插件执行时你需要自定义一些操作, 插件开发者不知道你需要什么操作, 只能预留一个回调函数接口,供你传入回调函数,例如你写了一个下拉框插件, 功能是将模拟select操作, 那么当onchange的时候是需要使用者根据...

JS数组reduce()方法详解及用法总结

在JavaScript中,数组的reduce方法用于对数组中的所有元素执行累积运算。这个方法接收一个回调函数作为参数,该回调函数会为数组中的每个元素执行操作,并将结果返回以累积一个最终结果。首先,让我们了解一下reduce的基本语法。reduce方法的参数通常包括一个回调函数和可选的初始值。在没有提供初始值的情况下...

jsfilter是什么意思

jsfilter是JavaScript中常用的函数,它的作用是筛选和过滤目标数组中的元素。JavaScript中只有一个原生的过滤函数,即filter()函数。该函数可以传入一个回调函数,这个回调函数将处理数组中的每个元素并返回一个布尔值,该布尔值将决定数组中该元素是否被保留。我们可以使用jsfilter函数来过滤数组中的元素,只...

js数组的reduce方法能计算数组中每个元素出现的次数吗?

acc[val]++;} else { acc[val] = 1;} return acc;}, {});console.log(result); // {1: 1, 2: 2, 3: 3} ```在上面的代码中,reduce方法的第一个参数是一个reduce回调函数,这个函数会接收两个参数:累加器(acc)和当前元素(val)。因为我们想要求出每个元素出现的次数,所以我们...

刨析JS 中的forEach、for in、for of三类循环原理和性能

本文剖析 JS 中的三种循环:forEach、for in、for of 的原理与性能。首先,forEach 函数每次循环都会执行一次回调函数,接收三个参数,可选参数包括当前值、索引、数组自身,回调函数的 this 指向为可选参数。此循环主要用于遍历数组中的可枚举属性。值得注意的是,使用 return 在 forEach 中并不能中断...

JS数组reduce()方法详解及高级技巧

reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组。先看第一个例子:这里可以看出,上面的例子index是从1开始的,第一次的prev的值是数组的第一个值。数组长度是4...

callback javascript回调函数 js回调函数简单例子 javascript回调函数例子 js回调函数怎么写 前端回调函数 js中map() js回调函数的具体例子 js callback
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
Tina Jittaleela的个人资料中,她喜欢的歌手有哪些? 索兰娜特·尤潘农基本信息 李缇娜个人 老公坚决要离婚该如何挽回 老公要离婚态度坚决怎么挽回 听说我们用的手机其实很脏,用普通消毒不环保,有那种专门的紫光手电可以... 统一 哪个集团 金鼠标金鼠标网络营销大赛 江礼坤个人履历 金鼠标网络营销大赛奖项设置 不合格电动车名单有哪些? 什么是JS回调函数 电动车不能在室内或者阳台充电? 制作表格是怎么画直线 2021年电动车真不能开了吗? word文本中的四线三格怎么画 电动自行车不能停在哪些地? 新国标电动车不用上牌照吗 电动车不走了,是什么情况? 电动车不充满电可以使用吗 电动车突然不通电了是为什么? 电动车不能载人是谁提出的? 电动车突然不走了但是有电,这是怎么回事? 电动汽车不走了怎么回事? 电动车不走了但是有电怎么修理? 电动车不通电是什么原因? 炖牛棒骨筋的做法 电压力炖牛肉的家常做法 挖掘机的结构及工作原理是怎样的? 计算机原理与体系结构电子书txt全集下载 JS回调函数 js回调函数有什么用 js 如何写回调函数 js的回调函数怎么写, 请问如何理解js回调函数呢?希望能详细说明!非常感谢! js里面的回调函数怎么写 js回调函数有哪几种 js回调函数如何实现异步,给一个例子 javascript的回调函数里如何传递参数 JS钩子函数与回调函数区别 js怎样获取调用回调函数的参数值 js 回调函数返回值 JS 回调函数怎么指定函数调用者 各位大牛,我现在在JS方法中遇到回调函数的问题。请问一下回调函数是怎么... JS:回调函数,条件满足时回调A函数,不满足时回调B函数,可以吗? 从手机上如何进入个人中心 虎牙在手机上在哪退出公会 tcl 电视机用网络看直播电视要下载什么应用,到哪里下载? 那个网络电视直播的电视台多?在哪下载? 抖音pk助理的人数和对面一样的吗