我是JS的新手,我在编写/理解回调函数方面遇到了很多麻烦 比方说,我有以下代码,但我不想要
takeNumbersGreaterThan(5);
执行直到
insertNumbers();
已完成
numbers = [];
greaterThan = [];
insertNumbers();
takeNumbersGreaterThan(5);
insertNumbers(){
for (var i = 0; i<11; i++)
{
numbers.push(i)
}
}
takeNumbersGreaterThan(number){
for (var m = 0; m<numbers.length; m++)
{
if (numbers[m] > number)
{
greaterThan.push(numbers[m])
}
}
}
我该怎么做呢?
答案 0 :(得分:0)
如果我理解正确,您想要了解有关回调的更多信息,并且您想要使用它们。让我试着帮你使用你的代码。
如果你想在使用回调函数takeNumbersGreaterThan(5);
之后立即执行insertNumbers();
,你可以这样做:
numbers = [];
greaterThan = [];
insertNumbers(takeNumbersGreaterThan, 5);
function insertNumbers(callbackFunction, callbackFunctionParam){
for (var i = 0; i<11; i++)
{
numbers.push(i)
}
callbackFunction(callbackFunctionParam);
}
function takeNumbersGreaterThan(number){
for (var m = 0; m<numbers.length; m++)
{
if (numbers[m] > number)
{
greaterThan.push(numbers[m])
}
}
}
但这只是一个简单的例子,说明如何在计算后调用回调函数。这段代码可以改进。关键是,您可以将回调函数作为参数传递给函数,然后再执行此回调函数。
答案 1 :(得分:0)
你已经在那里了。您的代码几乎完全正确。 你刚刚缺少功能键工作声明。
下面的脚本向您展示了如何在insertNumbers之后运行takeNumbersGreaterThan。在我的示例中,我还更改了函数符号,以便将数组作为参数传递,并避免一些常见的错误&#34;被称为闭包。
var numbers = [];
var greaterThan = [];
var insertNumbers = function(numbers) {
for (var i = 0; i<11; i++)
numbers.push(i)
}
var takeNumbersGreaterThan = function(number, numbers, greaterThan){
for (var m = 0; m<numbers.length; m++) {
if (numbers[m] > number)
greaterThan.push(numbers[m]);
}
}
// run insert numbers
insertNumbers(numbers);
// run take numbers greater than
takeNumbersGreaterThan(5, numbers, greaterThan);
// log
document.write(greaterThan);
&#13;
答案 2 :(得分:0)
您的代码不使用任何异步调用,因此您需要使用任何回调来处理执行。但如果你想知道怎么做,这就是方法。
numbers = [];
greaterThan = [];
function insertNumbers(callback){
for (var i = 0; i<11; i++)
{
numbers.push(i)
}
callback(); // now execute the callback funtion
}
function takeNumbersGreaterThan(number){
for (var m = 0; m<numbers.length; m++)
{
if (numbers[m] > number)
{
greaterThan.push(numbers[m]);
}
}
console.log(greaterThan);
}
insertNumbers(function() { // here we send a functions as argument to insertNumbers which will execute when callback() is called
takeNumbersGreaterThan(5);
});
insertNumbers
采用称为“回调”的参数。完成insertNumbers
后,我们只需运行callback()
。在对insertNumber
的初始调用中,我们传递一个函数作为参数,一旦insertNumers
完成(或调用callback()
),就会执行该函数。
答案 3 :(得分:0)
代码(大部分)按顺序执行。在您提供的代码中,计算机按照您提供的顺序运行代码。首先,它创建一个新的数组对象并将其设置为数字变量,然后创建一个新的数组对象并将其设置为greaterThan变量。 然后,它运行insertNumbers函数。现在,计算机所做的是跳转到您在insertNumbers中定义的代码并执行所有代码。然后,在完成之后,它将返回执行它所在的第一行代码的初始线程。所以现在它将跳转到takeNumbersGreaterThan代码。所以在功能上,你不需要任何回调,因为你的代码不会做任何花费任意时间的事情。
在解释之后,您会看到takeNumbersGreaterThan在执行insertNumbers之后才会执行。
唯一没有顺序执行代码的时间是您开始执行多核/线程代码时。
当某些事情需要花费任意时间时(例如从磁盘读取数据或从网络请求数据)时,会使用回调。
回调可以存在,因为javascript(以及许多其他语言)中定义的函数作为代码中的对象存在。如果不将括号放在函数名后面,实际上就像任何其他变量一样引用函数对象。因此,您可以在代码中传递该函数对象以及其他代码。这就是本例中发生的事情。
setTimeout(myCallback, 5000)
function myCallback(){
console.log("5 seconds have passed");
}
因此,正如您所看到的,我可以使用我的函数myCallback
并将其提供给另一个函数(在此实例中为setTimeout
),以便在另一个函数完成任务后使用。
答案 4 :(得分:0)
首先要理解回调,你必须了解功能。要了解javascript中的函数,首先必须了解变量,值和函数。
几乎所有编程语言都可以处理值。因此,如果您已经完成了任何编程,那么您就可以了解哪些值是基本的(我将在这里大大简化值的类型,并将值和引用/指针引用为&#34 ;值&#34;。)
价值是一种东西。例如数字或字符串。因此22.31
是一个值,"Hello Dave"
是一个值。
大多数语言也有变量的概念(尽管不是这样)。变量是&#34;名称&#34;我们赋予值以便更容易处理值。例如,在下文中,x
是一个变量:
var x = 12;
..它的值是12。
变量允许我们做什么?它允许我们在计算中用值替换名称。就像数学一样。例如,如果x
为12
且我们知道我们可以将1
添加到12
,我们也可以这样做:
x + 1
在javascript函数中是值。例如,在下面我们将一个函数赋给变量:
function a () {return "Hello"}
var y = a;
由于变量的作用是允许您使用名称替换值,因此如果您可以使用语法a
调用函数a()
,则意味着您也可以使用变量{{ 1}}:
y
如果函数是值,则还意味着您可以将函数作为参数传递给其他函数。例如,以下是您通常在另一个函数中调用函数的方式:
y(); // returns "Hello"
如果您可以将函数作为变量传递,则意味着您可以执行以下操作:
function a () {return "Hello"}
function b () {return a() + " World"}
b(); // returns "Hello World"
如你所见。回调并不特别。它们只是因为javascript函数遵循与其他值(如数字,数组和字符串)相同的规则这一事实的结果。
从上面的示例中可以看出,对函数function a () {return "Hello"}
function b () {return "Bye"}
function c (functionVariable) {return functionVariable() + " World"}
c(a); // returns "Hello World"
c(b); // returns "Bye World"
的两次调用都返回一个值。因此,函数c
即使接受回调也不是异步的。因此,回调可以用于同步和异步代码。
同步回调的一个很好的例子是c
方法。它对数组进行排序,但接受一个可选的回调,以便您定义排序方式(按字母顺序,数字顺序,按姓氏等)。
现在忘了ajax或网络代码。让我们看看一个场景,它使异步代码使用回调的原因更加明显。
比如说你有一个按钮。现在,当用户单击此按钮时,您希望发生某些事情。你是怎么做到的?
大多数人做的第一件事可能是这样的:
Array.sort()
行。这是一个无限循环,仅检查按钮是否被点击而没有其他内容。那么您如何期望浏览器更新UI并跟踪鼠标?这引导我们接下来的人们试图做的事情:
while (1) {
if (button.isClicked) {
doSomething();
}
}
行。大。但是有两个问题。首先,如果有人要编写像Google Charts或jQuery这样的库或者与UI有关的任何内容,他们要么编写自己的while (1) {
if (button.isClicked) {
doSomething();
}
else {
updateUI();
}
}
循环,要么必须手动将其功能复制/粘贴到while循环中。这不规模。其次,更重要的是,这是低效的。 while循环将使用100%CPU时间检查按钮。如果浏览器可以告诉我们何时点击按钮,那么它会不会更好。
幸运的是,javascript函数只是值。您可以将某个功能传递给浏览器,并告诉它在有人点击按钮时执行您的功能:
while(1)...
注意:注意将函数视为变量和调用函数之间的区别。如果要将函数视为变量,只需使用名称即可。如果要调用函数,请使用
等大括号button.addEventListener('click', doSomething);
。
有两个原因可以解释为什么每个人都坚持制作异步API,尤其是在javascript等语言中。
首先,低级文件和网络I / O是异步的。这意味着如果您想与数据库或服务器通信或读取文件,则需要将其实现为异步。此外,javascript是单线程的。因此,如果您使用I / O函数的同步版本,您将冻结其他所有内容。
其次,事实证明,在很多情况下(但肯定不是全部)异步,单线程编程与同步多线程编程一样快或有时甚至更快。
综合起来,上述两个原因在js社区中产生了社会压力,以确保所有I / O代码都是异步的,以保持速度优势而不会阻止其他人的代码。