http://blog.csdn.net/luoweifu/article/details/41466537
In Javascrip, a function is a built-in class object, which means that it is a type of object that can be used for the management of built-in objects just like other objects of the string, Array, number, and object classes. Because the function is actually an object, it can be "stored in a variable, passed to (another) function by argument, created inside a function, and returns the result value from the function." Because function is a built-in object, we can pass it as an argument to another function, defer execution to the function, or even return it after execution. This is the essence of using a callback function in JavaScript. The remainder of this article will fully learn the JavaScript callback function. The callback function may be the most widely used functional programming technique in JavaScript, and perhaps just a small piece of JavaScript or jquery code will leave a mystery to the developer, and reading this article may help you eliminate the mystery.
The callback function comes from a well-known programming paradigm- functional programming , at the basic level, where functional programming specifies the parameters of a function. Functional programming Although the current scope of use has become smaller, but it has been "professional smart" programmers as a kind of difficult to understand technology, previously, and the future will be so.
Fortunately, functional programming has been elaborated by the General people like you and me can also understand and use. One of the main techniques of functional programming is the callback function, which you will soon read that implementing a callback function is as simple as passing a generic parameter variable. This technology is so simple that I wonder why it is often included in the high-level topic of JavaScript.
What is a callback or advanced function?
A callback function is considered an advanced function, an advanced function that is passed as a parameter to another function (called "otherfunction"), and the callback function is called (or executed) within the otherfunction. The essence of a callback function is a pattern (a pattern that solves common problems), so a callback function is also called a callback pattern.
Consider the following callback functions that are commonly used in jquery:
//Note that the item in the click method‘s parameter is a function, not a variable.//The item is a callback function$("#btn_1").click(function() { alert("Btn 1 Clicked");});
As seen in the previous example, we pass a function to the parameter of the click Method, and the click Method invokes (or executes) the callback function we pass to it. This example gives a typical way to use the callback function in JavaScript and is widely used in jquery.
Savor a typical example of another basic javascript:
var friends = ["Mike", "Stacy", "Andy", "Rick"];friends.forEach(function (eachName, index){console.log(index + 1 + ". " + eachName); // 1. Mike, 2. Stacy, 3. Andy, 4. Rick});
Once again, we passed an anonymous function in the same way (a function without a function name) to the Foreach method as a foreach parameter.
So far, we have passed an anonymous function as a parameter to another function or method. Before looking at other more complex callback functions, let's take a look at how callbacks work and implement a callback function of our own.
How is the callback function implemented?
We can use a function like a variable, as an argument to another function, in another function as the return result, and call it in another function. When we pass a callback function as a parameter to another function, we pass only the definition of the function and do not execute it in the argument.
When the containing (called) function has a callback function defined in the parameter, it can be called at any time (that is, callback).
This means that the callback function is not executed immediately, but rather "callback" it (as its name) in the specified position within the function body containing the function. So, even if the first example of jquery looks like this:
//The anonymous function is not being executed there in the parameter. //The item is a callback function$("#btn_1").click(function() { alert("Btn 1 Clicked");});
The anonymous function is called in the function body of the Click function, even if there is no name, it can be accessed by the containing function through the arguments object.
The callback function is a closed packet.
When you pass a callback function as a parameter to another function, the callback function is executed somewhere within the body of the containing function function, as if the callback function is defined in the body of the function that contains the function. This means that the callback function is closed, and if you want to learn more about closures, refer to the author's other post understand JavaScript Closures with Ease. It is known that the closure function can access the scope of the containing function, so the callback function can access the variable that contains the function, even the global variable.
Basic principles of implementing callback functions
Simply put, there are a few principles to follow when implementing a callback function yourself.
Use a named function or an anonymous function as a callback
In the preceding jquery and foreach examples, we define anonymous functions in the parameters that contain the function, which is one of the common forms of using the callback function, and the other is often used in the form of defining a function with a name and passing the function name as an argument to another function, for example:
?// global variablevar allUserData = [];// generic logStuff function that prints to consolefunction logStuff (userData) { if ( typeof userData === "string") { console.log(userData); } else if ( typeof userData === "object") { for (var item in userData) { console.log(item + ": " + userData[item]); } }}// A function that takes two parameters, the last one a callback functionfunction getInput (options, callback) { allUserData.push (options); callback (options);}// When we call the getInput function, we pass logStuff as a parameter.// So logStuff will be the function that will called back (or executed) inside the getInput functiongetInput ({name:"Rich", speciality:"JavaScript"}, logStuff);// name: Rich// speciality: JavaScript
Passing parameters to the callback function
Because the callback function is executed just like a normal function, we can pass parameters to it. You can pass a callback function as a parameter to any property that contains a function (or a global property). In the previous example, we passed the options containing the function as arguments to the callback function. The following example lets us pass a global variable or local variable to the callback function:
//Global variablevar generalLastName = "Clinton";function getInput (options, callback) { allUserData.push (options);// Pass the global variable generalLastName to the callback function callback (generalLastName, options);}
Make sure the callback is a function before executing
Before calling, it is often advisable to ensure that callbacks passed in through parameters are a required function. In addition, making the callback function optional is also a good practice.
Let's refactor the GetInput function in the example above to make sure that the callback function is properly checked.
function getInput(options, callback) { allUserData.push(options); // Make sure the callback is a function if (typeof callback === "function") { // Call it, since we have confirmed it is callable callback(options); }}
If the GetInput function is not properly checked (checking whether callback is a function or passed in by argument), our code will cause a run-time error.
Problems with the callback function that contains this object
When the callback function is a method containing the This object, we must modify the method that executes the callback function to protect the contents of this object. Otherwise the This object will point to the Global Window object (if the callback function is passed to the global function), or to the containing function. Let's take a look at the following code:
// Define an object with some properties and a method// We will later pass the method as a callback function to another functionvar clientData = { id: 094545, fullName: "Not Set", // setUserName is a method on the clientData object setUserName: function (firstName, lastName) { // this refers to the fullName property in this object this.fullName = firstName + " " + lastName; }}function getUserInput(firstName, lastName, callback) { // Do other stuff to validate firstName/lastName here // Now save the names callback (firstName, lastName);}
In the following example code, when Clientdata.setusername is executed, This.fullname does not set the property fullname in the Clientdata object, but instead sets the FullName in the Window object. Because Getuserinput is a global function. This behavior occurs because the this object points to the Window object in the global function.
getUserInput ("Barack", "Obama", clientData.setUserName);console.log (clientData.fullName);// Not Set// The fullName property was initialized on the window objectconsole.log (window.fullName); // Barack Obama
Protect this object with the call or Apply function
We can solve the problem in the previous example by using the call or Apply function. So far, we know that every function in JavaScript has two methods: Call and apply. These methods can be used to set the contents of this object inside a function and to pass the content to the object that the function argument points to.
Call takes the value of used as the This object inside the function as the first parameter, and the remaining Arguments to is passed to the function is passed individually (separated by commas of course). The Apply function ' s first parameter is also the value of be used as the thisobject inside the function and the last PA Rameter is a array of values (or the arguments object) to pass to the function. (The paragraph is too awkward to translate, let the original experience)
This sounds complicated, but let's look at how easy it is to use apply and call. To solve the problem in the previous example, we use the Apply function as follows:
//Note that we have added an extra parameter for the callback object, called "callbackObj"function getUserInput(firstName, lastName, callback, callbackObj) { // Do other stuff to validate name here // The use of the Apply function below will set the this object to be callbackObj callback.apply (callbackObj, [firstName, lastName]);}
By using the Apply function to set the This object correctly, we can now execute the callback function correctly and set the FullName property in the Clientdata object correctly.
// We pass the clientData.setUserName method and the clientData object as parameters. The clientData object will be used by the Apply function to set the this object?getUserInput ("Barack", "Obama", clientData.setUserName, clientData);// the fullName property on the clientData was correctly setconsole.log (clientData.fullName); // Barack Obama
We can also use the call function, but in this case we use the Apply function.
Multiple callback functions are also allowed
We can pass multiple callback functions to another function, just like passing multiple variables. This is a typical example of an AJAX function using jquery:
function successCallback() { // Do stuff before send}function successCallback() { // Do stuff if success message received}function completeCallback() { // Do stuff upon completion}function errorCallback() { // Do stuff if error received}$.ajax({ url:"http://fiddle.jshell.net/favicon.png", success:successCallback, complete:completeCallback, error:errorCallback});
Questions and solutions for "Callback Hell"
Asynchronous code execution is a simple way to execute in any order, and sometimes it is quite common to have many levels of callback functions, and you look like the following code. The messy code below is called "Callback hell" because it's a cumbersome code that contains a lot of callbacks. I saw this example in Node-mongodb-native, MongoDB drives node. js. The sample code is like this:
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(); }); }); }); }); });});
You are unlikely to encounter this problem in your own code, but if you run into it (or stumble into it later), there are two ways to solve the problem.
- Name and define your function, and pass the function name as a callback instead of defining an anonymous function in the parameter list of the main function.
- Modularity: Divide your code into modules so that you can spare a chunk of code to do special work. You can then introduce this model into your large application.
??
Implement your own callback function
Now you fully understand (I'm sure you understand that if you don't read it quickly again) JavaScript uses the features of the callback and see that the callbacks are used so simple but powerful. You should see if your code has the opportunity to use the callback function, and you can consider using callbacks when you have the following requirements:
- Avoid duplicate code (dry-do not Repeat yourself)
- It's better to implement abstractions where you need more common functionality (you can handle various types of functions).
- Enhanced maintainability of code
- Enhance the readability of your code
- There are more custom features.
Implementing your own callback function is simple, in the following example, I can create a function to complete the work: Get user data, use user data to generate a common poem, use user data to welcome users, but this function will be a messy function, everywhere is if/else judgment, There are even many restrictions that cannot be performed on other functions that the application may need to process user data.
Instead, I let the implementation add a callback function, so that the main function gets the user data and can pass the user's full name and gender to the parameters of the callback function and execute the callback function to accomplish any task.
In short, the Getuserinput function is generic and can perform multiple callback functions with various functions.
// First, setup the generic poem creator function; it will be the callback function in the getUserInput function below.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");}//The callback, which is the last item in the parameter, will be our genericPoemMaker function we defined above.function getUserInput(firstName, lastName, gender, callback) { var fullName = firstName + " " + lastName; // Make sure the callback is a function if (typeof callback === "function") { // Execute the callback function and pass the parameters to it callback(fullName, gender); }}
Call the Getuserinput function and pass the Genericpoemmaker function as a callback:
getUserInput("Michael", "Fassbender", "Man", genericPoemMaker);// Output/* Michael Fassbender is finer than fine wine.Altruistic and noble for the modern time.Always admirably adorned with the latest style.A Man of unfortunate tragedies who still manages a perpetual smile.*/
Since the Getuserinput function only handles input from the user data, we can pass any callback function to it. For example, we can pass a greetuser function like this.
function greetUser(customerName, sex) { var salutation = sex && sex === "Man" ? "Mr." : "Ms."; console.log("Hello, " + salutation + " " + customerName);}// Pass the greetUser function as a callback to getUserInputgetUserInput("Bill", "Gates", "Man", greetUser);// And this is the outputHello, Mr. Bill Gates
As in the previous example, we called the same getuserinput function, but this time we performed a completely different task.
As you can see, the callback function provides a wide range of functions. Although the example mentioned earlier is very simple, think about how much you can save and how to better abstract your code when you start using a callback function. Come on! When you get up in the morning, think about it before you go to bed at night, and think about it when you rest ...
We often note the following when using callback functions in JavaScript, especially today's web application development, in third-party libraries and frameworks
- Asynchronous execution (such as reading a file, sending an HTTP request)
- Event monitoring and processing
- To set the timeout and time interval method
- Generalization: Code Simplicity
What is a callback or advanced function?