函数实际上是对象:它们能被“存储”在变量中,能作为函数参数被传递,能在函数中被创建,能从函数中返回;
回调函数
一个函数被作为参数传递给另一个函数(在这里我们把另一个函数叫做“otherFunction”),回调函数在otherFunction中被调用。
注意到click方法中是一个函数而不是一个变量
//它就是回调函数
$("#btn_1").click(function() {
alert("Btn 1 Clicked");
});
//或者
function click() { // 它就是回调函数
alert("Btn 1 Clicked");
}
$("#btn_1").click(click);
回调函数是怎样运作的
因为函数在Javascript中是第一类对象,我们像对待对象一样对待函数,因此我们能像传递变量一样传递函数,在函数中返回函数,在其他函数中使用函数。当我们将一个回调函数作为参数传递给另一个函数是,我们仅仅传递了函数定义。我们并没有在参数中执行函数。我们并不传递像我们平时执行函数一样带有一对执行小括号()的函数。
需要注意的很重要的一点是回调函数并不会马上被执行。它会在包含它的函数内的某个特定时间点被“回调”(就像它的名字一样)
实现回调函数的基本原理
使用命名函数或者匿名函数作为回调
像之前的例子一样,第一种方法就是匿名函数作为回调(使用了参数位置定义的匿名函数作为回调函数)。第二种方式就是命名函数作为回调(定义一个命名函数并将函数名作为变量传递给函数)
传递参数给回调函数
//第一种方法:匿名函数作为回调函数
var generalLastName = "Cliton";
function getInput(options, callback){
var arr = [];
arr.push(options);
//将全局变量generalLastName传递给回调函数
callback(generalLastName,arr);
}
getInput({name:"Rich",speciality:"Javascript"}, function(generalLastName,arr){
console.log(generalLastName + ":" + arr[0].speciality) // Cliton:Javascript
});
//第二种方法:命名函数作为回调函数
var generalLastName = "Cliton";
function getInput(options, callback){
var arr = [];
arr.push(options);
//将全局变量generalLastName传递给回调函数
callback(generalLastName,arr);
}
function call(generalLastName,arr){
console.log(generalLastName + ":" + arr[0].speciality) // Cliton:Javascript
}
getInput({name:"Rich",speciality:"Javascript"}, call);
在执行之前确保回调函数是一个函数
function getInput(options, callback){
//确保callback是一个函数
if(typeof callback === "function"){
//调用它,既然我们已经确定了它是可调用的
callback(options);
}
}
回调地狱(回调十八层地狱)
var p_client = new Db('integration_tests_20', new Server("127.0.0.1", 27017, {}), {'pk':CustomPKFactory});
p_client.open(function(err, p_client) {
p_client.dropDatabase(function(err, done) {
p_client.createCollection('test_custom_key', function(err, collection) {
collection.insert({'a':1}, function(err, docs) {
collection.find({'_id':new ObjectID("aaaaaaaaaaaa")}, function(err, cursor) {
cursor.toArray(function(err, items) {
test.assertEquals(1, items.length);
// Let's close the db
p_client.close();
});
});
});
});
});
});
解决方案:
1.给你的函数命名并传递它们的名字作为回调函数,而不是主函数的参数中定义匿名函数。
2.模块化L将你的代码分隔到模块中,这样你就可以到处一块代码来完成特定的工作。然后你可以在你的巨型应用中导入模块。
创建你自己的回调函数
//callback,参数的最后一项,将会是我们在上面定义的genericPoemMaker函数
function getUserInput(firstName, lastName, gender, callback) {
var fullName = firstName + " " + lastName;
if (typeof callback === "function") {
callback(fullName, gender);
}
}
function genericPoemMaker(name, gender) {
console.log(name + " is finer than fine wine.");
console.log("Altruistic and noble for the modern time.");
console.log("Always admirably adorned with the latest style.");
console.log("A " + gender + " of unfortunate tragedies who still manages a perpetual smile");
}
getUserInput("Michael", "Fassbender", "Man", genericPoemMaker); // 第一种方法:命名函数作为回调函数
getUserInput("Michael", "Fassbender", "Man", function(name, gender){ // 第二种方法:匿名函数作为回调函数
console.log(name + " is finer than fine wine.");
console.log("Altruistic and noble for the modern time.");
console.log("Always admirably adorned with the latest style.");
console.log("A " + gender + " of unfortunate tragedies who still manages a perpetual smile");
});
网友评论