JavaScript Advanced Programming (3rd Edition) Learning notes 7 JS function (ON) _ Basics

Source: Internet
Author: User
Tags function definition
Variable Type

Before you say a function, say the variable type first.

1, variable: variable in nature is the name of the memory space.

2, variable data type: Refers to the variable can store the value of the data type, such as number type, Boolean type, object type, etc., in ECMAScript, the variable data type is dynamic, you can change the data type of the variable at run time.

3. Variable type: Refers to the type of the variable itself, in ECMAScript, there are only two types of variables: value type and reference type. When the data type of a variable is a simple data type, the variable type is the value type, and when the variable's data type is an object type, the variable type is the reference type. You can also say that the data type of a variable is a variable type without ambiguity.

So what's the difference between a value type and a reference type? The main thing is that when the variable type is a value type, a variable stores the value of the variable itself, and when the variable type is a reference type, the variable stores not the variable value, but rather a pointer to the value of the variable, accessing the variable value of the reference type, first taking the pointer, and then getting the variable value based on the pointer. If you assign a variable value of a reference type to another variable, the end result is that both variables point to a variable value, and modify one of them to be modified to the other at the same time:
Copy Code code as follows:

var a = {
Name: ' Linjisong ',
Age:29
};
var B = a;//Assigns the variable A of the reference type to the variable b,a, b at the same time points to the object that a starts to point to
B.name = ' Oulinhai '//Modify the object that B points to, that is, modify the object that a points to
Console.info (a.name);//oulinhai
b = {//re-assign the variable, but B has not changed the object that the original point to, that is, the object that a points to does not change
Name: ' Hujinxing ',
Age:23
};
Console.info (a.name);//oulinhai

OK, about the variable type first of all, if you continue to the memory data structure, the fear of sinking can not float up.

Function

If the object is a room, then the function is a magical effect of the room. The function is the object first, and then the function object has many magical functions ...

1. function

(1) function is an object

The function is also an object, and the function used to create the function object instance is the built-in function () function (the creation of the object instance requires functions, and the function is an object instance, does it make you have the puzzle of having a chicken first or having an egg first?) Don't be a dead end, as long as the chicken can lay eggs, eggs can hatch the chicken on the line, who first or left to the philosopher it, but the function of this object, and the general object is very different, so that the function object instance when using typeof return is not object but function.

(2) The function name is a reference type variable that points to the function object
Copy Code code as follows:

function fn (p) {
Console.info (P);
}
Console.info (FN);//fn (P), you can use FN as a generic variable to access
var b = fn;
B (' function ');//function, you can use a function call to B, stating that the object that B points to (that is, the object that the original FN points to) is a function

Note: With respect to the function name, in the strict mode of ES5, eval and arguments are not allowed, of course, the parameter name can not use these two (I think unless you are a professional hacker, you will not use these as identifiers to use it).

2. Function Creation

(1) As an object, a function has a similar creation to a normal object, using new to invoke the constructor function (), which can accept any number of arguments, the last argument as the function body, and all the preceding arguments as the function's formal arguments, The preceding formal argument can also be passed as a parameter using a comma, in general form:
Copy Code code as follows:

var fn = new Function (p1, p2, ..., pn, body);
Or
var fn = Function (P1, p2, ..., pn, body);
Or
var fn = new Function ("P1, p2, ..., pn", Q1, Q2, ..., qn, body);
Or
var fn = Function ("P1, p2, ..., pn", Q1, Q2, ..., qn, body);

For example:
Copy Code code as follows:

var add = new Function (' A ', ' B ', ' return a + b; ');
Console.info (Add (2,1));//3
var subtract = Function (' A ', ' B ', ' return a-b; ');
Console.info (Subtract (2,1));//1
var sum = new Function (' A,b ', ' C ', ' return a + B + C; ');
Console.info (sum (1,2,3));//6

This way to create a function, will parse two of the code, a normal parsing, once analytic function body, efficiency will affect, but more suitable for the function body needs dynamic compilation.

(2) Because of the particularity of the function object itself, we can also use the keyword function to create functions:
Copy Code code as follows:

function Add (A, b) {
return a + B;
}
Console.info (Add (2,1));//3
var subtract = function (A, b) {
return a-b;
};
Console.info (Subtract (2,1));//1

As you can see, there are two ways to create functions using the Function keyword: function declarations and function expressions. Both of these ways can achieve the desired effect, so what is the difference between them? That's what we're going to talk about here.

3, function declarations and function expressions

(1) from the formal distinction, in the ECMA-262 specification, you can see:
Copy Code code as follows:

Function declaration: Function Identifier (parameter list (optional)) {Functional Body}
Functions expression: function Identifier (optional) (argument list (optional)) {function Body}

There is no difference except that the identifier of the function expression is optional, but we can also learn that there must be a function expression without a function name. Of course, with the function name, we can only judge from the context.

(2) from the context of the distinction, this is simple, that is, only allow expressions to appear in the context must be a function expression, only allowed to declare the context of the occurrence of a function declaration must be. Give some examples:
Copy Code code as follows:

function fn () {};//functions Declaration
function fn () {} (); exception, function declaration cannot call directly
var fn = function fn () {};//functions expression
(function fn () {});//functions expression, in group operation characters
+FUNCTION fn () {console.info (1);} ();//1, a function expression that appears after the operator +, so you can call it directly, or you can use other operators, such as new
New function fn () {console.info (2);} ();//2, function expression, after the new operator
(function () {
function fn () {};//functions Declaration
});

(3) Difference: Why do we have to spend so much effort to differentiate between function declarations and function expressions? Nature is because of their differences, the biggest difference between them is that the declaration will be promoted, about the declaration of Ascension, in the previous basic syntax of the article in the global scope of the declaration of Ascension has been discussed, we have to review the conclusions there:

A, the engine parsing, the first will parse the function declaration, and then resolve the variable declaration (parsing will not overwrite the type), and finally execute the code;

B, when parsing a function declaration, the type (function) is resolved at the same time, but will not execute, parsing the variable declaration, only the variable is resolved, not initialized.

There are also some examples to illustrate (recall), but there is no example of a declaration with the same name, here is a supplementary:
Copy Code code as follows:

Console.info (typeof fn);//function, declaring elevation, taking function as the standard
var fn = ';
function fn () {
}
Console.info (typeof fn);//string, because the code has been executed, here the FN type becomes string
try{
FN ();//is already a string type, cannot be invoked, throws type exception
}catch (e) {
Console.info (e);//typeerror
}
fn = function () {console.info (' fn ');};/ /If you want to invoke FN, you can only use the function expression to assign to FN
fn ();//fn, you can call

Console.info (typeof gn);//function
function gn () {
}
var gn = ';
Console.info (typeof gn);//string

You can see that, regardless of whether the variable declaration is before or after, when declaring a promotion, the function declaration takes precedence, but after declaring the elevation, because the variable initialization is to be performed, and the function declaration is no longer initialized (the function type is resolved at Ascension), the subsequent output becomes a string type.

Line 3rd above defines a function, and then the 7th line is called immediately, the result is not! You should be aware of the importance of keeping the global namespace clean, or else you might encounter "I clearly defined a function in the code but I can't call" this ghost thing, and conversely, if you want to make sure that your defined function is available, it's best to use a function expression to define, of course, You need to risk damaging the code of others.

And here's the question, how do we make sure that the variable type changes at initialization rather than when the variable declaration is raised? Look at the following code:
Copy Code code as follows:

Console.info (typeof fn);//function
function fn () {
}
VAR fn;
Console.info (typeof fn);//function

As you can see, declaring a promoted type is a function, and because there is no initialization code, the final type does not change.

There is one more thing to note about function declarations and function expressions, and look at the following code:
Copy Code code as follows:

if (true) {
function fn () {
return 1;
}
}else{
function fn () {
return 2;
}
}
Console.info (FN ());//in Firefox Output 1, in opera Output 2, in opera to declare the promotion, the following declaration will overwrite the previous same level declaration

if (true) {
gn = function () {
return 1;
};
}else{
gn = function () {
return 2;
};
}
Console.info (GN ());//1, all browser output is 1

In the ECMAScript specification, the identifier of a named function expression belongs to an internal scope, and the identifier of a function declaration belongs to the definition scope.
Copy Code code as follows:

var sum = function fn () {
var total = 0,
L = arguments.length;
for (; l; l--)
{
Total + = Arguments[l-1];
}
Console.info (typeof fn);
return total;
}
Console.info (sum (1,2,3,4));//function,10
Console.info (FN (1,2,3,4));//referenceerror

Above is the result of a named function expression running in Firefox, which can be accessed within the scope of a function, but a reference exception is accessed in the global scope. However, named function expressions are parsed by both function declarations and function expressions in IE browsers prior to IE9, and two objects are created, but the IE9 has been modified.

In addition to the global scope, there is also a function scope, in the function scope, to participate in the Declaration of the Promotion competition is also the parameters of the function. The first thing to be clear is that the function scope does not exist when the function is defined, only when the function is actually called to the function scope.
Copy Code code as follows:

Parameters and internal variables, parameters first
function fn (inner) {
Console.info (inner);//param
Console.info (other);//undefined
var inner = ' inner ';
var other = ' other ';
Console.info (inner);//Inner
Console.info (other);
}
fn (' param ');

parameters and internal functions, internal functions first
function gn (inner) {
Console.info (inner);//inner () function
Console.info (inner ());//undefined
function inner () {
return to other;
}
var other = ' other ';
Console.info (inner);//inner () function
Console.info (inner ());
}
GN (' param ');

Through the above output, we derive priority: Internal function declaration > function Parameter > Internal variable declaration.

One of the processes inside this is: first, the internal function declaration is promoted, the function name type is set to the function type, then the function parameter is parsed, and the actual parameter value is assigned to the formal parameter, and then the internal variable declaration is promoted, only the declaration is raised, not initialized, if there are duplicate names, and the back of the same priority is covered in front, The priority is not overwritten (the priority is resolved, and the lower priority is no longer resolved).
To illustrate, this is just my inference based on the output, as for the background implementation, it is possible that the steps are completely reversed, and each step overwrites the previous step, even starting from the middle, and then making a priority flag to determine whether it needs to be overwritten, and of course, in terms of efficiency, I should infer that the process will be better. In addition, the global scope is actually a simplified version of the function scope, with no function arguments.

Here is no longer a comprehensive example, it is recommended that this article and the previous basic grammar of the article read together, may be more effective. On the priority and coverage, also leads to the following to say a question.

4. Function overload

The function is an object, and the function name is a reference type variable that points to the function object, which makes it impossible to implement the overload as in the general object-oriented language:
Copy Code code as follows:

function fn (a) {
return A;
}
function fn (a,b) {
return a + B;
}

Console.info (FN (1)); NaN
Console.info (FN (1,2));//3

Don't wonder why line 8th exports Nan, since the function name is just a variable, the two-time function declaration is parsed in turn, and the function that is eventually pointed to by the variable is the second function, and the 8th line only passes in 1 arguments, and in the function, B is automatically assigned to undefined, then added to 1, and the result is Nan. Instead of a function expression, it may be better to understand, but only assigned two times, the natural later assignment will cover the front:
Copy Code code as follows:

var fn = function (a) {return A;}
fn = function (a,b) {return a + B;}

So, in ECMAScript, how do you implement overloading? Recall that a simple data type wrapper object (Boolean, number, String) can either create an object as a constructor or transform a data type as a transformation function, which is a typical overload. This overload is actually discussed in the previous article:

(1) Overloaded according to the function, the general format of this method is:
Copy Code code as follows:

function fn () {
if (this instanceof FN)
{
Function 1
}else
{
Function 2
}
}

Although this approach is feasible, it is obvious that the effect is limited, such as overloading only two of times, and can only overload the case that contains the constructor. Of course, you can extend the overload by combining apply () or call () or even the new bind () in ES5 to dynamically bind the this value inside the function, but this already has the meaning of overloading the function's internal property.
(2) overload based on function intrinsic property
Copy Code code as follows:

function fn () {
var length = Arguments.length;
if (0 = length)//Put the literal to the left is the custom brought from Java, because if the comparison operator is written in the assignment operator (0=length), the compiler will prompt me to error. If you are not accustomed to this way, please forgive me
{
return 0;
}else if (1 = length)
{
return +arguments[0];
}else{
Return (+arguments[0]) + (+arguments[1]);
}
}

Console.info (FN ());//0
Console.info (FN (1));//1
Console.info (FN (true));//1
Console.info (FN (1,2));//3
Console.info (FN (' 1 ', ' 2 '));//3

This is the use of function internal property arguments to implement overloading. Of course, the internal overload can be a variety of ways, you can also combine typeof, instanceof and other operators to achieve the functionality you want. As for the internal properties arguments what is the specific? This is the next thing to say.

5. Function Internal Property arguments

In a nutshell, the function internal property, is only in the function body access to the property, because the function is only when the function is called to execute, so the function internal properties are only in the function call will be resolved, each call will have a corresponding resolution, so have dynamic characteristics. This attribute has: this and arguments, here first look at the arguments, in the next article to say this.

(1) The list of parameters in the function definition is called the formal parameter, and the arguments that are actually passed in at the time of the function call are called actual parameters. The General Class C language, requires that the actual parameter be consistent with the formal parameter in the function call, but there is no restriction between the two in the ECMAScript, you can have 2 form arguments when you define it, pass in 2 actual parameters when you call, but you can also pass in 3 actual parameters. You can also pass in only 1 actual parameters, even if you do not pass any of the parameters. This feature is the basis for overloading using the intrinsic properties of functions.

(2) The formal parameter can even take the same name, except that the value that follows is taken as the value of the formal parameter when it is actually passed in (in which case you can use arguments to access the previous actual parameter):
Copy Code code as follows:

function gn (A,A) {
Console.info (a);
Console.info (Arguments[0]);
Console.info (Arguments[1]);
}
GN (1,2);//2,1,2
GN (1);//undefined,1,undefined

This can actually be explained by the previous conclusion of this article about the elevation of the declaration: the previous overlay with the priority, and the function argument parsing the value at the same time. Of course, in this way, security is problematic, so in the strict mode of ES5, the formal parameters of the duplicate name are forbidden.

(3) The value of the actual parameter is accepted by the formal parameter, but what if the actual parameter and the formal parameter are inconsistent? The answer is to use arguments to store, in fact, even if the actual parameters and formal parameters are consistent, there are arguments objects, and hold and have accepted the actual parameters of the formal parameters of the synchronization between. Refine this sentence to understand:

arguments is a class array object that can access arguments elements, such as Arguments[0, arugments[1, through square brackets and indexes, as you would access an array element.
arguments is a class array object that, in addition to the properties and methods inherited from object (some of which have been overridden), has its own properties, such as length, callee, and caller, where length represents the number of actual arguments (the number of formal arguments). That is the function attribute length), callee represents the current function object, and caller is defined only for the caller of the function attribute, and the value is undefined.
arguments is a class array object, but is not a true array object, can not directly call the Array object arguments method, if you want to invoke, you may first use Array.prototype.slice.call (arguments) Converts an array object first.
arguments saves the actual arguments passed in when the function is invoked, the No. 0 element saves the first actual argument, and the 1th element holds the second actual argument, and so on.
arguments saves the actual parameter value, and the formal parameter also holds the actual parameter value, which has a synchronization relationship, modifies one, and the other changes.
The synchronization between arguments and formal parameters only exists when the formal parameters actually receive the actual parameters, and no such synchronization relationship exists for formal parameters that do not receive actual parameters.
arguments objects, although very powerful, but also in terms of performance, there is a certain loss, so if not necessary, do not use, recommend or prioritize the use of formal parameters.
Copy Code code as follows:

FN (0,-1);
function fn (PARA1,PARA2,PARA3,PARA4) {
Console.info (fn.length);//4, number of formal parameters
Console.info (arguments.length);//2, number of actual parameters
Console.info (Arguments.callee = = fn);//true,callee object pointing to FN itself
Console.info (Arguments.caller);//undefined
Console.info (Arguments.constructor);//object () instead of array ()
try{
Arguments.sort ()//class array is not an array after all, cannot call an array method directly, throw an exception
}catch (e) {
Console.info (e);//typeerror
}
var arr = Array.prototype.slice.call (arguments);//Convert an array first
Console.info (Arr.sort ());//[-1,0], it's already sorted.

Console.info (PARA1);//0
Arguments[0] = 1;
Console.info (PARA1);//1, modifying arguments[0], changes the formal parameters synchronously Para1

Console.info (Arguments[1]);//-1
Para2 = 2;
Console.info (Arguments[1]);//2, modify the formal parameter para2, will be synchronized modify ARGUMENTS[1]

Console.info (PARA3);//undefined, the formal parameter not passed in the actual parameter is undefined
ARGUMENTS[2] = 3;
Console.info (arguments[2]);//3
Console.info (PARA3);//undefined, formal parameters that do not accept actual arguments do not have a sync relationship

Console.info (Arguments[3]);//undefined, the actual parameter is not passed in, the value is undefined
PARA4 = 4;
Console.info (PARA4);//4
Console.info (Arguments[3]);//undefined, for incoming actual arguments, does not synchronize
}

After testing, the synchronization between arguments and formal parameters is bidirectional, but the 66th page of JavaScript Advanced Programming (3rd edition) says one-way: Modifying formal parameters does not change arguments. This may be another bug in the original book, or it may be that Firefox has extended the specification. However, this also lets us know that even if the classics are so, there is still the possibility of bugs, all when the actual operation of the subject.

• Combined with arguments and its attribute callee, it is possible to decouple the function name by calling itself inside the function, so that even if the function is assigned to another variable, the function name (which is also a variable) is assigned, and can be guaranteed to run correctly. The typical examples are the factorial function, the Fibonacci sequence, and so on.
Copy Code code as follows:

Find factorial
function factorial (num) {
if (num <= 1)
{
return 1;
}else{
return num * factorial (num-1);
}
}
var fn = factorial;
factorial = null;
try{
FN (2);//Because the function internally recursively invokes factorial, and factorial has been assigned null, an exception is thrown
}catch (e) {
Console.info (e);//typeerror
}

Fibonacci Series
function Fibonacci (num) {
if (1 = num | | 2 = num) {
return 1;
}else{
Return Arguments.callee (num-1) + Arguments.callee (num-2);
}
}
var gn = Fibonacci;
Fibonacci = null;
Console.info (GN (9))//34, the use of Arguments.callee, the realization of the function object and function name decoupling, can be performed normally

Recursive algorithm is very concise, but because to maintain the running stack, the efficiency is not very good. On the optimization of recursion, there are many very good methods of the cream, here is not in-depth.

It should be noted that Arguments.callee has been disabled in the strict mode of ES5, at which point a named function expression can be used to achieve the same effect:
Copy Code code as follows:

Fibonacci Series
var Fibonacci = (function f (num) {
Return num <= 2? 1: (f (num-1) + f (num-2));
});
var gn = Fibonacci;
Fibonacci = null;
Console.info (GN (9))//34, using a named function expression to implement the function object and function name decoupling, you can normally execute

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.