Learning JavaScript with me functions and function expressions _javascript tips

Source: Internet
Author: User

1, function declaration and function expression

In ECMAScript, the two most commonly used methods of creating functions are function expressions and function declarations, and the difference between the two is a bit faint, because the ECMA specification is only a bit clear: the function declaration must have an identifier (Identifier) (the name of the function that everyone often says). And a function expression can omit this designator:

Function declaration: Functionfunction name (parameter: optional) {functions body}

Function Expressions: functionfunction name (optional) (parameters: optional) {Functional body}

So, as you can see, if you don't declare the function name, it's definitely an expression, but if you declare the function name, how do you decide whether it's a function declaration or a function expression? ECMAScript is differentiated by context, and if function foo () {} is part of an assignment expression, it is a function expression, if function foo () {} is contained in a function body, or at the top of the program, So it's a function declaration.

function foo () {}//declaration because it is part of the program
var bar = function foo () {};//expression, because it is part of the assignment expression

new function bar () {};//Expression, because It is the new expression

(function () {
 function bar () {}//declaration, because it is part of the function Body
}) ();

There is a very subtle difference between an expression and a declaration, and first, a function declaration is parsed and evaluated before any expression is parsed and evaluated. Even if your statement is in the last line of the code, it will be parsed/evaluated before the first expression in the same scope, as in the following example, the function FN is declared after alert. But when alert executes, FN already has a definition:

Alert (FN ());

function fn () {return
 ' Hello world! ';
}

Also, there is a caveat that function declarations can be used in conditional statements, but not standardized, which means that different environments may have different execution results, so it's best to use a function expression: because there is no block-level scope in a conditional statement

Don't do this!
//Because some browsers return this function of first, and some browsers return the second

if (true) {
 function foo () {returns
 ' first ';
 }
}
else {
 function foo () {return
 ' second ';
 }
}}
Foo ();

Instead, in this case, we want to use Var foo with the function expression
;
if (true) {
 foo = function () {return
 ' a '
;}} else {
 foo = function () {return
 ' second ';}
 ;
} Foo ();

The actual rules for a function declaration are as follows:

A function declaration can only appear in the body of a program or function. In terms of clauses, they cannot appear in blocks (block) ({...}). , for example, you cannot appear in an if, while, or for statement. Because block (blocks) can contain only statement statements, they cannot contain source elements such as function declarations. On the other hand, a closer look at the rules also reveals that the only way that an expression can appear in a block is to make it part of an expression statement. However, the specification explicitly stipulates that an expression statement cannot begin with a keyword function. In effect, this means that a function expression also cannot appear in a statement statement or block (because block is made up of statement statements).

2. Named function expression

The reference to a named function expression, of course, is that it has to have a name, the preceding example var bar = function foo () {}; is a valid named function expression, but one thing to remember: The name is valid only in the newly defined function scope, Because the specification stipulates that identifiers cannot be valid within the scope of the perimeter:

var f = function foo () {return
 typeof foo;//function--->foo is valid inside scope
};
Foo is used externally for
typeof Foo;//"Undefined"
f ();//"function"

So, what's the use of a named function expression, if that's required? Why do you have to name it?

As we said at the beginning: Give it a name is to make debugging process more convenient, because in debugging, if each item in the call stack has its own name to describe, then the debugging process is too cool, feel different.

tips: Here's a little question: in ES3, the scope object of a named function expression also inherits the properties of the Object.prototype. This means that simply naming a function expression also introduces all the attributes in the Object.prototype to the scope. The results may be unexpected.

var constructor = function () {return null;}
var F = function f () {return
 Construcor ();
}
f (); {in ES3 environment}

The program appears to produce null, but it actually produces a new object. Because a named function expression inherits the Object.prototype.constructor (that is, the constructor of Object) within its scope. Like the WITH statement, this scope is affected by dynamic changes in the Object.prototype. Luckily, ES5 corrected the error.

A reasonable solution to this behavior is to create a local variable with the same name as the function expression and assign a null value. Even in an environment where the function expression declaration is not raised incorrectly, using VAR to declare a variable ensures that the variable g is still bound. Setting variable g to null ensures that duplicate functions can be garbage collected.

var f = function g () {return
 ;
}
var g =null;

3, the debugger (call stack) of the named function expression

Just said, the real use of the name function expression is debugging, then how to use it? If a function has a name, the debugger will display its name on the calling stack when it is debugged. Some debuggers (Firebug) sometimes name your functions and display them, let them have the same role as those that apply the function, but usually these debuggers only install simple rules to name, so there's not much value, so let's take a look at an example: without a named function expression

function foo () {return
 bar ();
}
function bar () {return
 baz ();
}
function Baz () {
 debugger;
}
Foo ();

Here we use 3 function declarations with names
//So when the debugger goes to the debugger statement, the Firebug call stack looks very clear 
//Because it clearly shows the name
Baz
Bar
foo
expr_test.html ()

By looking at the call stack's information, we can easily know that Foo called Bar, and Bar called Baz (and Foo itself has a expr_ Test.html the global scope of the document is called), however, there is a more cool place, is just said firebug for anonymous expression name function:

function foo () {return
 bar ();
}
var bar = function () {return
 baz ();
}
function Baz () {
 debugger;
}
Foo ();

Call stack
Baz
bar ()//See? 
foo
expr_test.html ()

Then, when the function expression is slightly more complex, the debugger is not so smart, we can only see the question mark in the call stack:

function foo () {return
 bar ();
}
var bar = (function () {
 if (window.addeventlistener) {return
 function () {return
  baz ();}
 ;
 }
 else if (window.attachevent) {return
 function () {return
  baz ();
 };
}}) ();
function Baz () {
 debugger;
}
Foo ();

Call stack
baz
(?) ()//This is a question mark. Show as anonymous function (anonymous function)
foo
expr_test.html ()

Also, when you assign a function to multiple variables, there is a depressing problem:

function foo () {return
 baz ();
}
var bar = function () {
 debugger;
};
var baz = bar;
bar = function () { 
 alert (' spoofed ');
Foo ();

Call stack:
bar ()
foo
expr_test.html ()

At this point, the call stack shows that Foo called Bar, but that's not the case, because Baz and another function that contains alert (' spoofed ') do a reference exchange.

In the final analysis, only the function expression name, is the most commissioned method, that is, the use of named function expressions. Let's use the expression with the name to rewrite the example above (note that the names of the 2 functions returned in the expression block immediately called are bar):

function foo () {return
 bar ();
}
var bar = (function () {
 if (window.addeventlistener) {return
 function bar () {return
  baz ();}
 ;
 }
 else if (window.attachevent) {return
 function bar () {return
  baz ();
 };}}
) ();
function Baz () {
 debugger;
}
Foo ();

Again to see the clear call stack information Yes!
Baz
bar
foo
expr_test.html ()

OK, the end of the entire article, we have a closer understanding of JavaScript, I hope we are more and more like small set for everyone to organize the article, continue to focus on learning JavaScript with me a series of articles.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.