The way JavaScript functions are declared and invoked is a tiresome cliché, but there's something like that, you say it again and I say it again. Every time I see the JavaScript function written in the book or blog has four kinds of calling way, I will think of: anise word has four kinds of writing, you build it?
Although there are a bunch of bugs, JavaScript is fascinating. The core of the many beautiful features of JavaScript is the function of being a top-level object (first-class objects). Functions are created like other normal objects, assigned to variables, passed as parameters, as return values, and hold properties and methods. Functions, as top-level objects, give JavaScript powerful functional programming capabilities, as well as flexibility that is less easily controlled.
1. Function declaration
A variable declaration first creates an anonymous function and assigns it to a specified variable:
var f = function () {//function body};
Usually we don't have to care whether the scope of the expression on the right of the equal sign is global or a closure, because it can only be referenced by the variable F on the left side of the equal sign, and should focus on the scope of the variable F. If a reference to a function is corrupted (f = null) and the function is not assigned to any other variable or object property, the anonymous function is destroyed by the garbage collection mechanism because all references are lost.
You can also use function expressions to create functions:
Unlike a variable, this declarative method assigns a value to a built-in property name for a function. The function is also assigned to a variable with the same name as the current scope. (The function's Name property, configurable, enumerable, and writable are all false)
function f () {//function body}
Console.log (f.name);//"F"
JavaScript variables have one thing in particular, which is to advance the declaration of a variable, the function declaration of an expression, and the definition of the entire function, so you can use it before the function definition:
Console.log (F.name); "F"
Console.log (f);//F ()
function f () {//function body}
The declaration of a function expression is elevated to the top of the scope, and try the following code, which is not the focus of this article:
var a = 0;
Console.log (a); 0 or a ()?
Crockford recommends using the first way to declare a function forever, and he thinks the second way is to loosen the requirement that a function must be declared and used before it can cause confusion. (Crockford is a "conscientious programmer" like the "conscientious artist" in Russell's mouth, which is a metaphor for Wittgenstein's words).
function declaration
Seems to be
var F = function f () {};
's Shorthand. and
expression that creates a function and assigns the built-in name property to "B". Then assign the function to variable a, you can use a () to invoke it externally, but you cannot use B (), because the function is assigned to a, so no longer automatically creates a variable B unless you use var B = A declares a variable B. Of course, the name of this function is "B" rather than "a".
You can also use function constructors to create functions:
var f = new Function ("A,b,c", "return a+b+c;");
This approach actually generates an anonymous function within the global scope and assigns it to the variable F.
2, Recursive call
Recursion is used to simplify many problems, which requires calling itself in a function body:
A simple factorial function
var f = function (x) {
if (x = = 1) {return
1;
} else {return
x * F (x-1);
}
};
The great flexibility of functions in JavaScript makes it difficult to use function names in recursion, and for the above variable declaration, F is a variable, so its value can easily be replaced:
The function is a value, it is assigned to FN, we expect to use FN (5) to calculate a value, but because the function is still referencing the variable F, so it does not work properly.
A functional declaration looks better, but it's a pity:
function f (x) {
if (x = = 1) {return
1;
} else {return
x * F (x-1);}
}
var fn = f;
f = function () {}; May been warning by browser
It seems that once we have defined a recursive function, we should be careful not to change the name of the variable easily.
It's all about functional invocation, and there are other ways in which functions are called, such as Object methods.
We often declare objects like this:
var obj1 = {
Num:5,
fac:function (x) {
/function body
}
Declares an anonymous function and assigns it to the object's properties (FAC).
If we want to write a recursive here, we need to refer to the property itself:
var obj1 = {
Num:5,
fac:function (x) {
if (x = = 1) {return
1;
} else {return
x * obj1 . FAC (X-1);
}
}
;
Of course, it also encounters the same problem as the function invocation method:
var obj2 = {FAC:OBJ1.FAC};
Obj1 = {};
OBJ2.FAC (5); Sadness
Method is assigned to the FAC property of the Obj2, the interior still refers to the OBJ1.FAC, so ... Has failed.
A different approach would improve:
var obj1 = {
Num:5,
fac:function (x) {
if (x = = 1) {return
1;
} else {return
x * THIS.FAC ( x-1);
}
}
;
var obj2 = {FAC:OBJ1.FAC};
Obj1 = {};
The This keyword gets the properties in the context of the function execution, so that when the OBJ2.FAC is executed, the Obj2 FAC property is referenced inside the function.
But functions can also be arbitrarily modified context to invoke, that is omnipotent call and apply:
Then the recursive function does not work properly.
We should try to solve this problem, remember the way of a function declaration mentioned earlier?
This type of declaration is called an inline function, although no variable B is declared outside the function, but within the function, B () can be used to invoke its own, so the inline
var fn = function f (x) {
//try If you write ' var f = 0; ' Here
if (x = = 1) {return
1;
} else {
retur n x * f (x-1);
}
};
var fn2 = fn;
fn = null;
Here's the difference between "var F = function f () {}" and "function f () {}"
var f = function f (x) {
if ( x = = 1) {return
1;
} else {return
x * F (x-1);}
};
var fn2 = f;
f = null;
var obj1 = {
num:5,
fac:function f (x) {
if (x = = 1) {return
1;
} else {return
x * F (x -1);}}
;
var obj2 = {FAC:OBJ1.FAC};
Obj1 = {};
OBJ2.FAC (5); Ok
var obj3 = {};
Obj1.fac.call (OBJ3, 5); Ok
In this way, we have a name that can be used internally, without worrying about who the recursive function is assigned to and how it is invoked.
The arguments object inside the JavaScript function has a callee attribute that points to the function itself. Therefore, you can also use Arguments.callee to invoke functions internally:
function f (x) {
if (x = = 1) {return
1;
} else {return
x * Arguments.callee (x-1);}
}
However, Arguments.callee is a property that is ready to be deprecated and is likely to disappear in future ECMAScript versions, and Arguments.callee cannot be used when "use strict" in ECMAScript 5.
The last suggestion is: If you want to declare a recursive function, use the new function in this way, the function created by the functions constructor compiles a function every time it is invoked, and a recursive call raises a performance problem-you will find that your memory is quickly depleted.
The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.