JavaScript Day 28. Callback Function ( 回呼函式 )

上一篇我们在讨论 AJAX 的时候,有另外提到 Callback Function,不知道怎麽的我突然想花更多的时间去研究这个 function,所以这一篇就用更多的 Callback Function 范例把它塞满好了 (?)

Callback Function,也称做「回呼函式」,在前面的例子中我们可以大概看到, Callback Function只会在满足某项条件以後被动的去执行,简单来说就是「在一个函式执行完後,会依照条件去执行传递进来的函式」。

直接进入范例:

var isFirst = function (callback) {
    console.log('is first!');
    callback(); // 执行传入的 isSecond()
}

// callback function
var isSecond = function () {
    console.log('is second!')
}
isFirst(isSecond);

isFirst 函式执行完以後才会执行 isSecond 函式,并且 isSecond 会被代入到 callback,isSecond 即为一个 Callback Function。

结果:

is first!
is second!

但这样其实看起来跟平常的函式没有什麽太大的不同,平常的函式不也是长这个样子吗?

var isFirst = function (callback) {
    console.log('is first!');
}

var isSecond = function () {
    console.log('is second!')
}

isFirst();
isSecond();

结果:

is first!
is second!

我们可以来试试比较明显的例子,以下面这个例子来说,isFirst 中加入了 setTimeoutsetTimeout 为非同步的处理方法,同步与非同步在前面文章有提到,它的第一个参数为时间到时要被执行的程序,第二个参数为延迟的时间 ( 豪秒 )。

var isFirst = function () {
		setTimeout(function() {
        console.log('is first!')
    }, 2000); // 非同步,2秒後才执行
}

var isSecond = function () {
    console.log('is second!')
}

isFirst();
isSecond();

结果:

is second!
// 2秒後
is first!

从结果来看 isFirst 函式被设定延迟,加上 setTimeout 是非同步方法,因此不会等到 isFirst 回传结果,而是先继续执行 isSecond 函式,那麽如果我们希望 isSecond 函式可以在印出 is first! 之後才执行呢?这时候就必须使用 Callback Function 来处理。

var isFirst = function (callback) {
		setTimeout(function() {
        console.log('is first!')
				callback();
    }, 2000); // 非同步,2秒後才执行
}

// callback function
var isSecond = function () {
    console.log('is second!')
}

isFirst(isSecond);

结果:

// 2秒後
is first!
is second!

可以看到,使用 Callback Function 之後,is second! 可以确保在 is first! 印出後才出现,符合 Callback Function 会在满足一个条件以後才会再次执行另一个程序的原则。

另外再塞一个看起来比较复杂一点点的 Callback Function 范例:

//定义函式
function prepare(ingredients, callback) {
       console.log("Preparing" + ingredients);
       callback();
}

//调用函式
prepare("onions and garlic", function chop() {
       console.log("Chopping" );
});

prepare() 代入了两个参数,第一个为 ingredients,然後使用 chop() 的 Callback Function 作为第二个参数,此时 chop() 会代入 callback(),力求简洁的写法把 chop() 直接代入到 prepare() 中,结果为:

Preparing onions and garlic
Chopping

呈上面的例子, Callback Function 也可以是匿名函式:

//定义函式
function prepare(ingredients, callback) {
       console.log("Preparing" + ingredients);
       callback();
}

//调用函式
prepare("onions and garlic", () => {
       console.log("Chopping" );
});

现在我们的 Callback Function 是匿名的,它不叫做「chop」了。

结果:

Preparing onions and garlic
Chopping

Callback Function 是作为另一个主函式传递参数的函式, Callback Function 在主函式内部执行,并且由主函式决定何时执行它。

现在已经知道执行 Callback Function 的主函式有权决定何时执行,而且不只这样,主函式能替Callback Function 决定的东西很多,它也可以将参数传递给 Callback Function。底下为带参数的Callback Function 例子:

//定义函式
function prepare(ingredients, callback) {
       console.log("Preparing " + ingredients);
			 // 这边替 Callback Function 加上了参数
       callback(ingredients);
}

//调用函式
prepare("onions and garlic", function chop(arg) { 
			 // chop() 代入 arg 参数
       console.log("Chopping " + arg);
});

这边我们不只是调用 chop() 这支 Callback Function,我们将它变成参数传入,并且告诉它在执行的时候回传 "Chopping " 以及参数。

结果:

Preparing onions and garlic
Chopping onions and garlic

虽然我觉得写到这里应该差不多了(X),但是 Callback Function 的好处比我原本想像的还更多,因此我只好继续写下去。不过好加在这是最後一个例子了,脑袋得以回氧再做冲刺,哈哈。

Callback Function 也是函式,这意思是说它也可以做任何函式能做的事情,这边有一个例子,假设我们希望回传底下这个结果:

Preparing onions and garlic
Chopping onions

为了呈现这样的结果,表示 Callback Function 必须过滤掉不要用的词。

function chop(ingredients){
     var value = ingredients.match(/\bonions\b/g);
     if (value){
				console.log("Chopping " + value);
		 } else {
				console.log("Not chopping");
		 }
}

在这个范例中,它必须确认 “ onions ” 这个词有没有在参数中,如果有就回传 “ Chopping onions ”,如果没有则回传 " Not chopping "。

function prepare(ingredients, callback) {
       console.log("Preparing " + ingredients);
       callback(ingredients); 
}

function chop(ingredients){
     var value = ingredients.match(/\bonions\b/g);
     if (value){
				console.log("Chopping " + value);
		 } else {
				console.log("Not chopping");
		 }
}

prepare("onions and garlic", chop);

最後这个例子可能复杂了一点,主要是它除了调用 Callback Function 之外,还另外使用了 match() 方法来查找字串是否有匹配,不过如果对 match() 方法是有理解的,这最後一个范例应该也还是不难懂,不妨在看这一范例的时候,先去了解一下 match() 方法,比较不会觉得恐慌 (?)

参考资料:

JavaScript 什麽是Callback函式 (Callback Function)?


<<:  DAY23神经网路(续一)

>>:  android studio 30天学习笔记 -day 22-Dagger 前言

Day 11 - Roman to Integer

大家好,我是毛毛。ヾ(´∀ ˋ)ノ 废话不多说开始今天的解题Day~ 13. Roman to In...

Python - pandas (vi) dataframe资料框之相关指令

程序码: import pandas as pd head5=pd.util.testing.mak...

《你的地图会说话? WebGIS与JavaScript的情感交织》结束,才是真正的开始。

一路走来 不知不觉已到了Day30了,这一天说长不长说短不短。 其实大概从Day5开始,就已经觉得很...

子元件向父元件传值与讯息

人类沟通需要技巧,程序语言靠的是方法。 我们除了可以透过 Props 来让父元件传值给子元件外,也...

Ruby基本介绍(七) && missing-number

本篇音乐分享 本篇文章会提到的 上一篇衍生题:include,与extend差异? missing-...