Exploration and summary of javascript functions

Source: Internet
Author: User
Tags bind closure constructor prev variable scope

I know that you prefer to read articles like "XX effect". After all, you can read them in just a few minutes. Most of the articles on the homepage are similar. I am not good at writing results, but I still offer a long article. After writing for a long time, the example is not complex, and the implementation is also the simplest way. It is a summary of the knowledge from thick to thin. Each vertex can be expanded.
Structure:
0. Function
1. First-class functions
2. The function is a parameter.
3. The function is returned.
4. Closure
5. Kerizhua
6. Function combination
7. MPs queue
8. Chain rules

In js, functions are very important. This article attempts to use the viewpoint of combination learning to derive common concepts in functions.
Here, we can make a little guarantee that, after looking at the end from the beginning, there will be a variety of concepts, such as "that is the case" and "that is the case !" Is simple but not simple.

Equipment preparation
1. What is the function used? Functions have three main functions:
1. Encapsulation logic
This can be said that in all languages, the initial meaning of a function is to encapsulate reusable code blocks and call them.
2. Provide scope
What is the scope? It refers to the visibility of variables. As we all know, js does not have a block-level scope. In general, the variable scope also has the global scope and the local scope. In js, functions are the smallest units that provide scopes.
3. It can be used as a constructor.
JavaScript is a prototype-based language that can be used using the new operator to implement class-based language usage. The responsibility for constructing functions in js falls into the function itself.

2. The function is a first-class citizen!
You must have heard of such a sentence. Everything in js is an object.
Remember the following sentence today. Everything in js is a value.
That's right! You have not heard the error.
The reason is that the function is designed as a first-class object.
So what is a first-class object?
The first-class object can be used as the value!
0. The function can have no name.

(Function (){})();

1. Functions can be stored as variables like numbers.

Var fun = function (){};

2. Functions can be stored in a structure like numbers.

Var fun = [1, function () {}];
Var fun2 = {x: function (){}};

3. A function can be used as a number as a function parameter.

Var a = function (){};
Var B = function (fun) {fun ()};
B ();

4. A function can be returned as a number.

Var a = function () {return function () {}}; 1.
5. Functions can be dynamically created like numbers.

2 + 3 * (function () {}) (); 1.
As for the first-class object, are there any other objects in js? Yes, [] Yes, {} Yes.
From this point of view, the function is designed as a data type, which is nothing to worry about. ("Undefined", "boolean", "string", "number", "object", and "function ")
So remember this sentence. Everything in js is an object and a value. It is a confrontation and unity. Greetings to Grandpa Marx.

5. In addition, function related materials need to be prepared.
Arguments, this, call, apply
These are basic materials. You can search for them on the Internet. There are countless similar articles on this website. I have written several articles...

6. Discard the burden
We need to lose the performance considerations, or we will miss a lot of beautiful scenery.

Starting

1. Basic prototype of functions

Var fun = function (a, B ){
Console. log (arguments );
Console. log (this );
Return a + B;
};
Fun (1, 2 );

It can be said that it is the simplest example of a function.
Here, let's talk a little about this, which prints global objects, such as windows in a browser. In strict mode, it is undefined. If you don't believe it, you can add "use strict" and debug it.

2. Take the function as the parameter
Jquery is much used, which is easy to understand.
Let's take the es5 method in the array as an example.
For example

[1, 2, 3]. forEach (alert); 1.
It looks strange. alert is a function that is passed in as a parameter and then called. The values 1, 2, and 3 are displayed respectively. In fact, there is nothing hard to understand.
In the following format?

[1, 2, 3]. forEach (function (value) {alert (value)}); 1.
No problem.

3. Return values using functions

Var getAlert = function (){
Return alert;
};
Var myAlert = getAlert ();
MyAlert (1 );

As expected, result 1 is displayed. What if getAlert is changed to the following? We should also know.

Var getAlert = function (){
Return function (value ){
Alert (value );
};
};

I'm afraid you will think, it's easy. I know that you are not boasting that my article is well written, but that you are talking about these things. No one knows. Are you still writing an article? Haha, Lao Yao's articles have always been from easy to difficult.

Okay. Let's start building blocks and take a journey with these simple things to see what the scenery is.

4. Closure
Let's take a look at the above getAlert. Well, this is a function. After running, a function is returned.
Slightly more complicated

Var fun = function (){
Var x = 0;
Return function (){
Alert (x );
};
};
Var f = fun ();
F ();

Well, the pop-up 0 is OK.
Don't underestimate the simplicity of a piece of code. Is the closure.
F call is a function call, and an x is encountered in it. The browser must find this variable.
The browser is based on the proximity principle. x = 0. No problem.
Then rewrite it a little bit,

Var fun = function (){
Var x = 0;
Return function (){
Alert (++ x );
};
};
Var f = fun ();
F ();
F ();

The pop-up is 1 and 2 respectively. Why is it not 1? It is equivalent to the following code:

Var x = 0;
Var f = function (){
Alert (++ x );
};
F ();
F ();

If this can be understood, the closure above can be understood. It is equivalent to a browser that opens a space for f to store the value of x.
What if I use another method?

Var fun = function (){
Var x = 0;
Return function (){
Alert (++ x );
};
};
Var f = fun ();
F ();
Var g = fun ();
G ();

At this time, both of them are popped up with 1. Why? Because fun returns two functions, and the browser saves two copies.
Equivalent to the following code:

Var x1 = 0;
Var f = function () {alert (++ x1 )};
Var x2 = 0;
Var g = function () {alert (++ x2 )};
F ();
G ();

Here we will talk about the closure (the function that can be returned is called the closure ). In fact, I have previously written the closure article. Here we repeat it to maintain a coherent mind and prepare for the future. Therefore, it is necessary to reiterate the three conditions for producing closures.
1. The called function is an internal declaration.
2. The called function is called outside the declared position function.
3. The called function references external variables.
The following function is not a closure and an error is reported.

Var fn = function (){
Alert (++ x );
};
Var fun = function (){
Var x = 0;
       
Return fn;
};
Var f = fun ();
F ();

Continue watching

Var fun = function (x ){
Return function (){
Alert (++ x );
};
};
Var f = fun (0 );
F ();
F ();

Is it a closure? Yes. The three conditions are met.
Check again

Var fun = function (x ){
Return function (x ){
Alert (++ x );
};
};
Var f = fun (0 );
F (1 );
F (1 );

This is not because the x referenced by the function is the x (form parameter) of the inner layer rather than the outer layer.

The concept of closure is over. Do you say we have to go there?
Isn't it a combination study? What if alert is a passed-in function?

Var sum = function (x, y) {alert (x + y )}
Var fun = function (call ){
Var x = 0, y = 0;
Return function (){
X ++;
Y ++;
Call (x, y );
};
};
Var f = fun (sum );
F ();
F ();

OK. The pop-up is actually 2 and 4. Well, it is indeed a closure.
But here we can introduce a new journey.

5. Kerizhua

Var curry = function (fun ){
Return function (arg ){
Fun (arg );
};
};
Var myAlert = curry (alert );
MyAlert (1 );

It's useless to look around the world. Isn't alert a hit.
Useful. This is used to answer a post a few days ago. Multiple real parameters of a function can be limited to one parameter. This is not mentioned here. We will continue to study colialization.

The above code is slightly changed.

Var curry = function (fun ){
Var x = 60;
Return function (y ){
Return fun (x, y );
};
};
Var sum = function (x, y) {return x + y };
Var sum60 = curry (sum );
Sum60 (5); // => 65

Var devide = function (x, y) {return x/y };
Var devide60 = curry (devide );
Devide60 (5); // => 12

Can we see the benefits of colihua? A sum function can create a sum60 function. A devide function can create a devide60. In general, curry is a tool for building functions by functions.

I don't want to limit the value to 60. Can the number to be specified be passed in as a parameter?

Var curry = function (fun, x ){
Return function (y ){
Return fun (x, y );
};
};
Var sum = function (x, y) {return x + y };
Var sum60 = curry (sum, 60 );
Sum60 (5); // => 65

I want a devide to create a devideBy60 function? Yes.
The code is as follows:

Var curry = function (fun, x ){
Return function (y ){
Return fun (y, x );
};
};

This involves a problem. I will talk about it later.
Next we will discuss the problem of horizontal expansion and vertical expansion for multiple parameters.
Expand horizontally. Take four parameters as an example.

Var curry = function (fun, x, y ){
Return funciont (z, w ){
Return fun (x, z, y, w );
        }
}

There are many writing methods like this.
In terms of concept, this horizontal expansion method is not currying. But we need to focus on the essence.
What is the essence? The essence is the transmission of delay parameters. It doesn't matter what you call this function. I am also called currying here. When you read other books, you will be fooled. Haha.
Continue with the example. For horizontal expansion, one of them is our bind simulation.

Var bind = function (fun, context ){
Return function (args ){
Return fun. apply (context, args );
        }
}

You can also write a placeholder method, which is more practical.
Here _ is used for placeholder

Var _ = {}; // as long as it is a reference, ensure that no error is reported.
Var curry = function (fun ){
Var rest = []. slice. call (arguments, 0 );
Rest. shift (); // rest = [1, _, 3, _]
Return function (){
Var args = []. slice. call (arguments, 0); // args = [2, 4]
Var finalArgs = rest. map (function (value, index ){
If (value = _){
Return args. shift ();
                        }
Return value;
}); // FinalArgs = [1, 2, 3, 4]
Return fun. apply (this, finalArgs );
        }
}
Var fun = function (a, B, c, d ){
Alert ("" + a + B + c + d );
}
Var f1 = curry (fun, 1, _, 3 ,_);
F1 (2, 4); // => 1234

The above code looks complicated. It should be understandable after reading a line. Here is just a simple implementation, without too much consideration.
Call, apply, and []. map methods. I assume you already have.

Vertical Expansion. Three parameters are used as an example.

Var curry = function (fun ){
Return function (z ){
Return function (y ){
Return function (x ){
Return fun (x, y, z );
                        }
                }
};
};
Var sum = function (x, y, z ){
Return x + y + z;
};
Var r = curry (sum) (5) (10) (15 );
Alert (r); // => 30

The above curry is expanded from right to left. If return fun (z, y, x) is changed, it is expanded from left to right.
Let's take a look at curry (sum) (5) (10) (15). Is this call quite appealing ???
I know what you want to say now? "However, it is useless." I guess it is correct.
If the parameter is a function, we can see that curry is a more semantic call.
As for the example, I haven't thought about it yet. I may make it up later.

The parameters and returned values are similar. Next we will mainly look at all the parameters are functions. What will happen?

6. Function combination

For ease of analysis, let's give an example.

Var sum = function (x, y ){
Return x + y;
};
Var minus = function (x, y ){
Return x-y;
};
Var power = function (x ){
Return x * x;
};

If we want to sum and then square, how can we write it.
The call is as follows,

Power (sum (1, 2) // => 9 1.
We can build a peace function sumPower

Var sumPower = function (x, y ){
Return power (sum (x, y ));
};

Well, this can be said to be the most direct way.
Power (sum () is a mathematical product of two functions. That is, the function combination is changed into a new function. This method is direct but not universal. For example, if I want minusPower, do I have to write it again. So we need to review the code. Because the function can be used as a parameter data transmission, can I transmit power and sum over again?
You can directly rewrite the following:

Var getSumPower = function (power, sum ){
Return function (x, y ){
Power (sum (x, y ))
};
};
SumPower = getSumPower (power, sum );
SumPower (1, 2 );

So now our task is to change getSumPower to a common function so that we can not only obtain
You can also get the minusPower.
Here I need to implement a compose function to achieve the following results:

Var newfunc = compose (f, g, h );
Newfunc (x) <=> f (g (h (x) 1.
2.
The implementation is as follows:

Compose = function (){
Var args = arguments;
Var start = args. length-1;
Return function (){
Var I = start;
Var result = args [start]. apply (this, arguments );
While (I --) result = args [I]. call (this, result );
Return result;
};
};

The implementation principle is still very simple. You can see it in a line. I don't need to talk about it. I just read the code again. If you have read the underscore Source Code Analysis series, you can see where you are trying to implement it. You just copied it from the ground up. I have tried this function for n times, and I can memorize it.
Use the following,

Var sumPower = compose (power, sum );
Var minusPower = compose (power, minus); 1.
2.
OK. Let's stop here for the combination of the landscape. If this problem is analyzed from the mathematical point of view.
For example, this problem is developed from the perspective of satisfying the associativity and exchange, that is, the theory of semi-groups. I guess I can write another article.
F (g (h (x) from the perspective of this call, the concept of pipelines can not be imagined.

7. MPs queue
The purpose of a pipeline is to throw the returned value to the next function as the initial value after a function is run. It is also a transfer baton. Pipeline and combination focus are different.
The combination focuses on how functions f, g, and h form a new function. Pipeline focuses on the process and whether or not it is called layer by layer.
The implementation is as follows:

Var pipeline = function (initValue ){
Var args = []. slice. call (arguments, 0 );
Args. shift ();
Return args. reduce (function (prev, next) {return next (prev)}, initValue );
};

Use:

Pipeline (4, function (x) {return x * 2;}, function () {return x * 3}); 1.
The last part describes the chain call.

8. Chain rules
Speaking of the chain rule, I'm afraid everyone will think, I know, it's not that the method finally returns this.
For example, jq

$ ('<Div> </div> 'salary .css ({height: '40px '}). attr ('id', 'newdiv '). appendTo ('body'); 1.
An example of this implementation is provided.

Var f = function (args ){
If (! (This instanceof f) return new f (args );
};
F. prototype = {
Fun1: function () {return this ;},
Fun2: function () {return this ;}
}
Var instance = f ();
Instance. fun1 (). fun2 ();

A little bit, do you see the if in the constructor? It indicates that the function call can be new or internal. This method is called a secure (secure) constructor.

What is the chain of the chain rule? It is the vertex operator. In general, the chained rule refers to the object before a vertex, which is the same object. What I want to mention here is the chain call in general cases.
For example

Var getArray = function (x, y) {return [x, y]}
GetArray (1, 2). map (function (x) {return x * x}). forEach (alert); 1.
2.
This code style is a bit of a pipeline style. Since it is a vertex operator, the returned value must be an object.
Let's assume that the chain call form is like this:

Object. fun1 (). fun2 (). fun3 () 1.
We use array reduce to simulate

["Fun1", "fun2", "fun3"]. reduce (function (prev, next ){
Return prev [next] ();
}, Obj );

The above implementation does not consider the parameter issue, so we have to have a storage structure to store the relevant data
See implementation

Var chain = function (obj ){
If (! (This instanceof chain) return new chain (obj );
This. start = obj;
This. data = [];
};
Chain. prototype = {
Link: function (methodName ){
Var args = []. slice. call (arguments, 0 );
Args. shift ();
This. data. push ({
Name: methodName,
Args: args
});
Return this;
},
Run: function (){
Return this. data. reduce (function (prev, next ){
Var name = next. name;
Var args = next. args;
Return prev [name]. apply (prev, args );
}, This. start );
        }
};

Let's take a rough look at the code. link is the storage, and run is the overall call.
The usage is as follows:

Chain ([1, 2, 3])
. Link ('map', function (x) {return x * x })
. Link ('foreach', alert)
. Run ();

This is directly used

[1, 2, 3]. map (function (x) {return x * x}). forEach (alert) 1.
What is the difference?
Chain is a kind of inertia chain. It is relatively lazy. I run it only when you call run. That is to say, we can splice the chain until you don't want to fight, and then run it to call the chain.

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.