JavaScript 的声明函数和匿名函数的区别
今天在公司没有太多任务,就把前几天挤压下来的问题一一解决了一下。突然发现javascript的函数直接的区别没有搞清楚。这里懒得翻译了,就直接把英文代码粘来了。
Javascript function declarations vs function operators
There are quite a few different ways to create a new function in javascript, but the two most common are using a function declaration or using the function operator.
This function is created using a function declaration:
function destroyDeathStar() { alert("Stay on target, stay on target"); }
This function is created using the function operator:
var destroyDeathStar = function() { alert("Stay on target, stay on target"); } destroyDeathStar();
The biggest difference between using a function declaration or a function operator is when the function is created. Functions made with a function declaration are moved to the top of the code and created before the rest of the function is run. Functions made with the function operator are created at runtime where they are in the javascript code.
Function declarations
Function declarations are the javascript 101 way to create a new function:
function destroyDeathStar() { alert("Stay on target, stay on target"); } destroyDeathStar();
When you use a function declaration, the function object will be created as the javascript is parsed, before the code is run. This is why you can call a function created with the function statement before it is declared:
destroyDeathStar(); function destroyDeathStar() { alert("Stay on target, stay on target"); }
This works because the javascript interpreter does something called hoisting when it is loading a new program or creating a new function object. It looks for any function declarations in the current scope and moves them to the beginning of the code. This is why you can call a function created by a function declaration before it is declared in the code.
So if you wrote some code that looks like this:
destroyDeathStar(); function destroyDeathStar() { alert("Stay on target, stay on target"); }
It would end up being executed like this:
var destroyDeathStar = function destroyDeathStar() { alert("Stay on target, stay on target"); } destroyDeathStar();
The function declaration syntax also automatically adds the new function object to the current scope. It creates a variable with the same name as the function which points to the newly created function object.
Because of this, all functions created with the function declaration must be given a name. They can not be anonymous functions. If the function did not have a name, it would not be possible to add it to the current scope and you would not be able to call it.
The function operator
If you’ve done any work with jquery, you’ve probably seen a function declared with the function operator:
var destroyDeathStar = function() { alert("Stay on target, stay on target!"); } destroyDeathStar();
The biggest difference between a function operator and a function declaration is when the function is created. Function operators aren’t affected by hoisting so they are evaluated where they occur in the source code as the code is run.
This is very useful because function creation can be affected by the surrounding logic. For example, if you put a function declaration into an if statement, it would get hoisted out of the if statement into the beginning of the scope. If you use a function operator no hoisting will happen so the function creation will stay inside the if statement:
var destroyDeathStar; if(pilot == "Luke Skywalker") { destroyDeathStar = function() { alert("May the force be with you"); } } else { destroyDeathStar = function() { alert("Gold Five to Red leader, lost Tiree, lost Dutch"); } } destroyDeathStar(); // result will depend on the value of pilot when the code is run
According to the javascript spec it’s not actually legal javascript to put a function declaration inside an if block. All the browsers let you do it, but they deal with it in different ways. Annoyingly, it will work the way you expect it to in Firefox because they have yet another type of function creation called the function statement but it will hoist the function out of the if statement in all other browsers.
The other result of not being affected by hoisting is that functions created by the function operator aren’t automatically added into the current scope as a variable. Instead the function operator returns the new function object and it is up to the code to do something with it.
The usual thing is to assign the return value from the function operator to a variable that you can use to invoke it:
// same name as the function that you can use to invoke it function destroyDeathStar() { alert("Stay on target, stay on target"); } destroyDeathStar(); // this example of using the function operator stores the new function // in a variable called destroyDeathStar2 var destroyDeathStar2 = function() { alert("Stay on target, stay on target!"); } destroyDeathStar2();
If you don’t do anything with the return value from the function operator, there is no way to invoke the function. It is perfectly valid javascript to do that, but doesn’t really have much point:
function() { alert("Stay on target, stay on target!"); } // no way to invoke the function
Since functions created with the function operator aren’t automatically added to the scope, they don’t have to have a name. They can be anonymous. Functions created with the function operator are usually created as anonymous functions since there isn’t much benefit giving the function a name since it’s not automatically added to scope:
var destroyDeathStar = function /* no name here – so is anonymous */ () { alert("Stay on target, stay on target!"); } // destroyDeathStar is a variable containing a reference to the function, not the function's name // read about anonymous functions if you'd like to know more destroyDeathStar();
The function operator is useful because it’s an expression
The function operator is a lot more flexible than a function declaration because it can be used wherever it is valid to use an expression.
You can use the function operator to declare a function when you are creating an object:
var jabbaTheHut = { laugh : function() { alert("ho ho ho ho"); } } jabbaTheHut.laugh();
When you are creating a list:
var toDoToday = [ function() { alert("Aren't you a little short for a storm trooper?") }, function() { alert("Boring conversation anyway") }, ]; for(var x=0; x<toDoToday.length; x++) { toDoToday[x](); }
To declare a function as a parameter when calling another function:
// function statement function itIsATrap(theTrap){ theTrap(); } // function operator itIsATrap(function() { alert("Many Bothans died to bring us this information"); });
This can be very convenient if you are creating single use functions like object methods or event handlers. The anonymous function syntax is more concise than declaring a function and then doing something with it as two separate steps. In JQuery code (and other similar libraries) this is used all the time:
$(document).ready(function() { alert("page has loaded."); });
You can also use the function operator it inside an if condition to actually control whether a function is created or not using programming logic:
var chooseSide; if(skywalker == "Luke Skywalker") { chooseSide = function() { return "jedi"; } } else { chooseSide = function() { return "sith"; } } alert(chooseSide());
Or inside any type of loop:
for(var x=0; x<=900; x++) { var myFunction = function() { alert("When " + x + " years old you reach, look as good you will not."); } myFunction(); }
That’s nice, but which should I use?
If you need to create a function inside an if statement or a loop, always use a function operator. The function declaration will not have the effect that you intended because it will be hoisted to the top of the code (unless you and all the people who will ever use your script are using Firefox because then it will become a function statement). Function declarations that are in if statements or loops will never consistently do what you expect cross browser.
If you are going to declare a function and use it only once and straight away, the function operator syntax is more concise than the function declaration. It is ideal for things like single line JQuery event handlers that toggle some CSS class.
Building up objects with methods is pretty much the same. Using the function operator to directly assign the method to the object means not having to go looking for the implementation. If you’re worried about performance, use the object prototype to declare the method only once for all the objects you create.
If you’re working in the global scope (writing javascript that is not inside a function), particularly if you are working on code that will be used by other people, you will want to avoid creating lots of variables that might conflict with other code. The function operator can be used with patterns such as namespacing to keep your code’s footprint as light as possible.
For any other functions that will be used a number of times, function declaration or function operator is a matter of personal preference. The function declaration is more concise and looks more like how you’d create a function in most other languages. If you’re using the function operator everywhere else and you want to make sure no one makes the mistake of putting a function declaration inside a conditional statement or a loop, then it might be worth considering mandating the function operator in your coding standards.
来源:http://helephant.com/2012/07/14/javascript-function-declaration-vs-expression/