请帮我理解关于回调的两件事.它们是我在强大的C#背景下无法掌握的最后一个JS怪异之处.

首先,为什么我们要将函数作为参数发送.我知道我们可以,但为什么.我会试一试我能想到的最简单的例子.因此,根据JS开发人员的说法,应该是这样的:

function simpleCallbackFn(){}

function simpleCallerFn(cb){ cb();}

simpleCallerFn(simpleCallbackFn);

为什么不这样做呢:

function simpleCallbackFn(){} // Same as before

function simpleCallerFn(){ 
  simpleCallbackFn();
} 

我们不传递回调,我们只是从调用者内部调用它.它在完全可见的范围内.我们就打第一个电话.

simpleCallerFn();

从调用者函数内部向我调用"回调"函数应该完全可以,并达到相同的结果.

第二,假设我需要使用带有参数的回调

function simpleCallbackFn(anArgument){}

function simpleCallerFn(cb){ 
   cb(anArgument);
}

我们知道这是行不通的 simpleCallerFn (simpleCallbackFn(anArgument));

根据JS开发者的说法,应该是这样的:

simpleCallerFn (() => simpleCallbackFn(anArgument));

我在想为什么不:

function simpleCallbackFn(anArgument){}

function simpleCallerFn(anArgument, cb){ 
   cb(anArgument);
}

然后进行初始呼叫,如下所示:

simpleCallerFn(anArgument, simpleCallbackFn);

然后结合我的第一种和第二种方法:

function simpleCallbackFn(anArgument){}

function simpleCallerFn(anArgument){ 
   simpleCallbackFn(anArgument);
}

simpleCallerFn(anArgument);

请.那个脚本让我感觉就像在怪胎马戏团一样.

谢谢

推荐答案

为什么不这样做呢:

function simpleCallbackFn (){} // Same as before

function simpleCallerFn (){ simpleCallbackFn ();}  

这当然是合法的代码,但只有在您提前确切知道要执行哪些代码的情况下才有可能.回调函数的意义在于,您可以在运行时决定要做什么.

例如,有一个内置函数,数组调用了.map.它获取一个数组并将其转换为新的array.您传入一个回调函数,指定如何执行该转换,.map将为数组的每个元素调用您的函数.没有其他方法可以实现.map,因为没有办法提前知道您想要进行什么转换.

const values = [1, 2, 3];
const doubled = values.map(val => val * 2);
// doubled contains [2, 4, 6]

顺便说一句,MAP的简化实现如下所示:

function map(callback) {
  const newArray = [];
  // where `this` is the input array -- values in my example
  for (let i = 0; i < this.length; i++) {
    newArray[i] = callback(this[i]);
  }
  return newArray;
}

我们知道这不会起作用,SimeCallBackFn(AnArgument);

没错.只说明它不起作用的原因:这条线的操作顺序是从内到外的.基本上,它的意思是"立即拨打simpleCallbackFn(anArgument),然后将结果传递到simpleCallerFn".因此,我们最终传入undefined,而不是回调函数.

另一方面,simpleCallerFn(() => simpleCallbackFn(anArgument));表示"用文本() => simpleCallbackFn(anArgument)创建函数,并将其传递到simpleCallerFn中".

我在想为什么不:

function simpleCallbackFn (anArgument){}

function simpleCallerFn (anArgument, cb){ 
  cb(anArgument);
}

如果您确定回调只想要一个参数传递给它,那么这是有效的.但如果他们需要2个或更多,这将不起作用,如果他们需要0,这将比必要的更令人头疼.

因此,让这段代码的用户创建回调函数的好处是,他们可以创建any个函数,满足他们所能想到的任何要求.

Javascript相关问答推荐

从连接字符串创建客户端时,NodeJS连接到CosmosDB失败

如何在表格上拥有水平滚动条,在正文页面上拥有垂直滚动条,同时还对html表格的标题使用位置粘性?

有没有可能使滑动img动画以更快的速度连续?

如何将Openjphjs与next.js一起使用?

虚拟滚动实现使向下滚动可滚动到末尾

为什么我的导航条打开状态没有在窗口addeventlistener(Reaction Js)中更新?

在Java中寻找三次Bezier曲线上的点及其Angular

未加载css colored颜色 ,无法将div设置为可见和不可见

如何在我的Next.js项目中.blob()我的图像文件?

SPAN不会在点击时关闭模式,尽管它们可以发送日志(log)等

将范围 Select 器添加到HighChart面积图

我的NavLink活动类在REACT-ROUTER-V6中出现问题

使用静态函数保存 node 前的钩子

无法向甜甜圈图表上的ChartJSImage添加可见标签

由于http.get,*ngIf的延迟很大

在AgGrid中显示分组行的单元格值

ReactJS Sweep Line:优化SciChartJS性能,重用wasmContext进行多图表渲染

带有JS模块模式的Rails的Importmap错误:";Net::ERR_ABORTED 404(未找到)&Quot;

如何从图表中映射一组图表-js使用REACT

对象作为react 子对象无效(已找到:具有键的对象{type,props}).如果要呈现一个子级集合,请改用数组