Learn the functions and expressions of javascript from me

  • 2020-11-03 21:59:56
  • OfStack

1, function declaration and function expression

In ECMAScript, the two most commonly used methods for creating functions are function expressions and function declarations, the difference between which is somewhat confusing because the ECMA specification specifies only one point: a function declaration must have an identifier (Identifier) (commonly known as the name of the function), whereas a function expression can omit this identifier:

function function name (argument: optional){function body}

Function expression: function function name (optional) (argument: optional){function body}

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


function foo(){} //  Declare, because it's programmed 1 Part of the 
var bar = function foo(){}; //  Expression, because it's an assignment expression 1 Part of the 

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

(function(){
 function bar(){} //  Declare, because it's the body of the function 1 Part of the 
})();

Expressions and statements there are 10 subtle differences, first of all, the function declaration is in any expression parsing and evaluated to be parsed and evaluated before, even if your statement at the end of the code 1 row, it will be in the same scope before the first expression is parsed/evaluation, refer to the following example, function fn is after alert statement, but in alert fn has a definition:


alert(fn());

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

In addition, there is one more point to remind you that although function declarations can be used in conditional statements, they are not standardized, which means that different environments may have different execution results, so in this case, it is better to use function expressions: there is no concept of block-level scope in conditional statements


//  Don't do it! 
//  Because some browsers will return first the function , and some browsers return no 2 a 

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

//  Instead, in this case, we're going to use functional expressions 
var foo;
if (true) {
 foo = function() {
 return 'first';
 };
}
else {
 foo = function() {
 return 'second';
 };
}
foo();

The actual rules for function declarations are as follows:

Function declarations can only appear in a program or function body. Syntactically, they do not appear in Block (block) ({... }), for example, cannot appear in if, while, or for statements. Because Block (block) can only contain Statement statements, not source elements such as function declarations. On the other hand, a closer look at the 1 rule also shows that the only situation in which 1 is possible for an expression to appear in Block (block) is as part 1 of an expression statement. However, the specification clearly states that expression statements cannot begin with the keyword function. This, in effect, means that functional expressions cannot also be found in Statement statements or Block (blocks) (because Block (blocks) is made up of Statement statements).

2. Named function expressions

var bar = function foo(){}; function foo(){}; Is a valid named function expression, but one thing to keep in mind is that this name is only valid within the scope of the newly defined function, because the specification states that the identifier cannot be valid within the scope of the periphery:


var f = function foo(){
 return typeof foo; // function --->foo It's valid within the internal scope 
};
// foo Used externally is not visible 
typeof foo; // "undefined"
f(); // "function"

Now, if we want to do that, what is the use of a named function expression? Why do we name them?

As we said at the beginning: giving it a name makes debugging easier, because when debugging, if each item in the call stack has its own name to describe, then debugging process is very pleasant, not a good feeling.

tips: Here's a small problem: In ES3, the scoped object of a named function expression also inherits the properties of ES63en.prototype. This means that simply naming a function expression also introduces all the attributes in Object.prototype into the scope. The results can be surprising.


var constructor = function(){return null;}
var f = function f(){
 return construcor();
}
f(); //{in ES3  The environment }

The program looks like it will produce null, but it will actually produce a new object. Because the named function expression inherits Object.prototype.constructor (that is, the constructor of Object) in its scope. As with with statement 1, this scope is affected by dynamic changes to ES76en.prototype. Fortunately, ES5 fixed this error.

A reasonable solution to this behavior is to create a local variable with the same name as the function expression and assign it to null. Even in environments where function expression declarations are not incorrectly promoted, re-declaring variables using var ensures that the variable g is still bound. Setting the variable g to null ensures that duplicate functions can be garbage collected.


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

3. Named function expressions in the debugger (call stack)

As I said, the real use of named function expressions is debugging, so how to use them? If a function has a name, the debugger will display its name on the call stack during debugging. Some debuggers (Firebug) will sometimes name and display your functions, giving them the same role as those who have the convenience of applying the function, but usually these debuggers only install simple rules for names, so it's not worth much. Let's take a look at an example: no naming function expressions


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

//  Here we're using it 3 A named function declaration 
//  So when the debugger goes to debugger When I say, Firebug Looks pretty clear on the call stack  
//  Because it shows the name very clearly 
baz
bar
foo
expr_test.html()

By looking at the call stack, it is clear that foo calls bar and bar calls baz (and foo itself is called within the global scope of the ES100en_test.html document), but one of the cool things about Firebug is its ability to name anonymous expressions:


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 a little more complex, the debugger is not so clever, and we 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
(?)() //  It's a question mark. It's an anonymous function (anonymous function)
foo
expr_test.html()

In addition, there are frustrating problems when assigning functions to multiple variables:


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 this is not the case. This problem is caused by a reference exchange between baz and another function containing alert(' spoofed').

After all, the most delegating approach is to give a function expression a name, which is to use a named function expression. Let's override the above example with a named expression (note that the two functions returned in the immediately called expression block are both named bar) :


alert(fn());

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

0

Ok, the whole article is over, everyone's understanding of javascript has come a step closer, I hope you more and more like this site for you to organize the article, continue to pay attention to learn javascript 1 series articles with me.


Related articles: