JavaScript之回调函数

149 阅读4分钟

这是我参与更文挑战的第7天,活动详情查看: 更文挑战

JavaScript之函数回调

什么是回调函数?

究竟什么是回调函数呢?其实回调函数也是个函数,它具有函数的所有特征,它可以有参数和返回值。如果单独给出一个函数,你是看不出来它是不是回调函数的。回调函数区别于普通函数,在于它的调用方式。只有当某个函数被作为参数,传递给另外一个函数,或者传递给宿主环境,然后该函数在函数内部或者在宿主环境中被调用,我们才称为回调函数。

回调函数有两种不同的形式,同步回调异步回调。通常,我们需要将回调函数传入给另外一个执行函数,那么同步回调和异步回调的最大区别在于同步回调函数是在执行函数内部被执行的,而异步回调函数是在执行函数外部被执行的。

1.引例

需要有前后执行顺序的时候。

let x = function () {
    console.log("I am called from inside a function")
};
let y = function (callback) {
    console.log('do something');
    callback();
}
y(x);
//结果
//do something
//I am called from inside a function

当y(x)执行到callback()的时候,x传入自己的函数体并执行.也就是先y后x.

2.回调函数

2.1 同步回调的例子

myArray.forEach(function) 对数组内的所有数据执行function

var myArray = ["1", "2", "3", "4"];
function handlerArray(indexName,index){ 
console.log(index + 1 + ". " + indexName); 
}
myArray.forEach(handlerArray)
//1. 1
//2. 2
//3. 3
//4. 4

在这段代码中,我们通过 JavaScript 自带的 forEach 方法来枚举数字中的每个项,这里的逻辑很简单:调用 forEach 时,需要使用回调函数 handlerArray 作为其参数; 在 forEach 方法内部,会遍历 myArray 数组,数组中的每个元素依次都会调用一次回调函数 handlerArray。 因为 handlerArray 是 forEach的参数,而且 handlerArray 是在 forEach 函数内部执行,所以这是一个同步回调。同步回调,就是只在栈里面执行。

2.2 异步回调例子-setTimeout

和同步回调函数不同的是,异步回调函数并不是在它的执行函数内部被执行的,而是在其他的位置(task queue里)和其他的时间点(setTimeout)被执行的

比如下面这段 setTimeout 代码:

function foo(){
	alert("Hello")
}
setTimeout(foo,3000)

在这段代码中,我们使用了 setTimeout 函数,setTimeout 的第一个参数 foo 就是一个回调函数,V8 执行 setTimeout 时,会立即返回,等待 3000 毫秒之后,foo 函数才会被 V8 调用(从任务队列到栈里面执行),foo 函数并不是在 setTimeout 函数内部被执行的,所以这是一个异步回调。

2.3 外部声明回调函数后调用-代码更方便拓展方法

使用回调函数前 实现一个两个参数的加法和乘法的函数

let calc = function(num1,num2,fn){
    if(fn==='add'){
        return num1+num2;
    }
    else if(fn==='multiply'){
        return num1*num2;
    }
}
console.log(calc(1,3,add));
console.log(calc(1,3,multiply));
//结果
//4
//3

使用回调函数后

let add = function (num1, num2) {
    return num1 + num2;
}
let muiltply = function (num1, num2) {
    return num1 * num2;
}
let calc = function (num1, num2, callback) {
    //保证不被传进来其他东西破坏 增强健壮性
    if (typeof callback === "function") {
        return callback(num1, num2);
    }
}
console.log('callback_add:', calc(3, 3, add));
console.log('callback_muiltply:', calc(2, 3, muiltply));

可以看到是在calc函数外部定义函数, 然后通过callback去调用, 相比之前会更方便添加新的方法.calc函数内部加入了判断callback类型,避免一些错误的输入.

在calc上添加新函数 nothing

//你可以很方便的添加函数到这个库中
let nothing = function (num1, num2) {
    console.log(`这是你的那两个数,${num1},${num2}`)
}

然后在calc函数下面调用

console.log('callback_nothing', calc(2, 3, nothing));
//结果
//这是你的那两个数,2,3

总结

通过以上了解了回调函数的两个种类,一个是同步回调函数,在回调函数是在执行回调函数的函数内部执行的;一个是异步回调函数,并不是在它的执行函数内部被执行的,而是在其他的位置(task queue里)和其他的时间点(setTimeout)被执行的,通过同步回调函数可以方便拓展相同参数的其他方法。