Advanced Front-end BASICS (7): function and functional programming

Source: Internet
Author: User
Tags closure definition
Among all the key knowledge that must be mastered in JavaScript, functions are a key point that we can easily ignore when learning. In the course of learning, there may be many people and many articles that tell you that object-oriented is very important and prototype is very important, but few people tell you that all the key and difficulties of object-oriented are as follows, almost all of them are closely related to functions. Among all the key knowledge that must be mastered in JavaScript, functions are a key point that we can easily ignore when learning. In the course of learning, there may be many people and many articles that tell you that object-oriented is very important and prototype is very important, but few people tell you that all the key and difficulties of object-oriented are as follows, almost all of them are closely related to functions.

Including the execution context, variable objects, closures, and this introduced in my previous articles, all of which are centered around functions.

I know that many people are eager to learn object-oriented, learning modules, learning popular frameworks, and then quickly become masters. However, I am very responsible for telling you that these basic functions are not understood to a certain extent, so your learning progress must be difficult.

Therefore, you must pay attention to functions!

I. function declaration, function expressions, anonymous functions, and self-executed Functions

The Application of functions in actual development can be summarized as function declaration, function expressions, anonymous functions, and self-executed functions.

Function Declaration

We know that there are two declaration methods in JavaScript: one is using var variable declaration, and the other is using function declaration.

Advanced in front-end (3): I have mentioned in the variable object explanation that the function declaration has a higher execution order than the variable declaration in the process of creating a variable object, that is, the function declaration we often mention is advanced. Therefore, no matter where the function is declared in the execution context, we can directly use the function in the same execution context.

fn();  // functionfunction fn() {    console.log('function');}

Function expression

Unlike function declaration, the function expression uses var for declaration, so we must determine whether the expression can be correctly used according to the var rule, that is, the variable declaration. We know that using var for variable declaration is actually two steps.

// Variable declaration var a = 20; // the actual execution sequence var a = undefined; // variable declaration, initial value undefined, variable escalation, and improved sequence of variable function declaration a = 20; // assign values to variables. This operation will not be upgraded.

In the same way, when we declare a function using the variable declaration method, it is a function expression that we often call. Function expressions are promoted in the same way as variable declarations.

Fn (); // error var fn = function () {console. log ('function ');}

The execution sequence in the preceding example is as follows:

Var fn = undefined; // variable declaration to raise fn (); // execute the fn = function () {// value assignment operation, and assign the reference of the following function to the fn console. log ('function ');}

Therefore, different declaration methods lead to some differences between function declaration and function expression usage. In addition, these two forms of functions are not different in use.

In the above example, the value assignment operation in the function expression is also frequently used in other places, so we can understand the relationship.

Add method function Person (name) {this. name = name; this. age = age; // Add the method this in the constructor. getAge = function () {return this. age;} this .} // Add the method Person to the prototype. prototype. getName = function () {return this. name ;}// add method var a = {m: 20, getM: function () {return this. m ;}}

Anonymous Functions

The assignment operation in function expressions is described above. An anonymous function, as its name implies, is a function that is not displayed for value assignment. It is used in scenarios where multiple parameters are input to another function.

var a = 10;var fn = function(bar, num) {    return bar() + num;}fn(function() {    return a;}, 20)

In the above example, the first parameter of fn is passed into an anonymous function. Although the anonymous function is not displayed for value assignment, we cannot reference it in the external execution context. However, inside the fn function, we assign the anonymous function to the variable bar, saved in the arguments object of the fn variable object.

// Create stage VO (fn) = {arguments: {bar: undefined, num: undefined, length: 2 }}// execution phase of the variable object during fn context execution // The variable object becomes an activity object, and the value assignment operation and executable code VO-> AOAO (fn) are completed) = {arguments: {bar: function () {return a}, num: 20, length: 2 }}

Since an anonymous function is passed into another function and will be executed in another function, we often call this anonymous function a callback function. For more information about anonymous functions, I will explain in more detail in the next article about colihua.

This application scenario of anonymous functions involves almost all the difficult-to-understand knowledge points of functions. Therefore, we must be clear enough about these details, if you still don't understand the evolution of variable objects, you must go back and read this article: frontend BASICS (3): variable objects

Function self-execution and block-level scope

In ES5, there is no block-level scope, so we often use the function self-execution method to simulate the block-level scope, which provides an independent execution context, combined with the closure, it provides the foundation for modularization.

(function() {   // ...})();

A module can usually include private variables, private methods, public variables, and public methods.

According to the one-way access of the scope chain, it is easy to know that in this independent module, the external execution environment cannot access any internal variables and methods, therefore, we can easily create private variables and private methods belonging to this module.

(Function () {// Private variable var age = 20; var name = 'Tom '; // Private method function getName () {return 'your name is '+ name ;}})();

But what should I do if there are a total of methods and variables? Do you still remember the features of closures we mentioned earlier? Yes, with closures, we can access the variables and methods in the execution context. Therefore, we only need to create a closure according to the closure definition, open the variables and methods that you think need to be made public.

(Function () {// Private variable var age = 20; var name = 'Tom '; // Private method function getName () {return 'your name is' + name ;} // common method function getAge () {return age;} // Save the reference in the variable of the external execution environment to form a closure to prevent the execution environment from being reclaimed by the garbage collection window. getAge = getAge ;})();

Of course, we have already emphasized the important role of closures in the module, but this knowledge point is really too important and needs to be understood and thoroughly mastered over and over again, to help you better understand closures, let's take a look at how jQuery uses our modules and closures.

// Create a module (function (window, undefined) using the function self-execution method {// declare the jQuery constructor var jQuery = function (name) {// actively in the constructor, returns a jQuery instance return new jQuery. fn. init (name);} // Add the prototype method jQuery. prototype = jQuery. fn = {constructor: jQuery, init: function (){...}, css: function (){...}} jQuery. fn. init. prototype = jQuery. fn; // rename jQuery to $, and save the reference on the window to form a closure. The jQuery constructor is developed externally, in this way, we can access all the methods mounted on the jQuery prototype window. jQuery = window. $ = jQuery ;}) (window); // in use, we directly execute the constructor, because in the jQuery constructor, the returned result is a jQuery instance through some means, so we don't need to use new $ ('# p1') each time ');

Here, we only need to understand the closures and modules. As for how the internal prototype chain is wound, why is it written like this, when talking about object-oriented, I will analyze it for you. The purpose of this example is to pay attention to functions, because they are everywhere in actual development.

Next, I will share an advanced and useful module application. As our projects become larger and larger, more data and States need to be stored. Therefore, we need a dedicated module to maintain the data. At this time, something called status manager came into being. The most famous status manager is not redux. Although redux is a bit uncertain for everyone who is still learning it, before learning it, we can simply use it, this gives you a general understanding of the implementation principles of the Status manager and lays a solid foundation for our future study.

Let's look at the code first.

// Self-execution creation module (function () {// states structure preview // states = {// a: 1, // B: 2, // m: 30, // o: {}//} var states ={}; // Private variable used to store status and data // determine the Data type function type (elem) {if (elem = null) {return elem + '';} return toString. call (elem ). replace (/[\ [\]/g ,''). split ('') [1]. toLowerCase ();}/*** @ Param name attribute name * @ Description get the value saved in states using the attribute name */function get (name) {return states [name]? States [name]: '';} function getStates () {return states ;} /** @ param options {object} key-Value Pair * @ param target {object} the property value of the object is the property of the object, only @ desc is input in recursion when the function is implemented to modify the state Tree by inputting a key-value pair, the usage is similar to setStates in the data or react of the applet */function set (options, target) {var keys = Object. keys (options); var o = target? Target: states; keys. map (function (item) {if (typeof o [item] = 'undefined') {o [item] = options [item];} else {type (o [item]) = 'object '? Set (options [item], o [item]): o [item] = options [item];} return item;})} // provides an external interface window. get = get; window. set = set; window. getStates = getStates;}) () // use the following set ({a: 20}); // Save the attribute aset ({B: 100 }); // Save the property bset ({c: 10}); // Save the property c // Save the property o. Its value is set ({o: {m: 10, n: 20}) // modify the m value set ({o: {m: 1000}) of the object o }}) // Add a c Attribute set ({o: {c: 100}) console to the object o. log (getStates ())

The reason why I say this is an advanced application is that we may use this idea in a single-page application. According to the knowledge we have mentioned, it is actually very simple to understand this example. The difficulty is estimated that the set Method is processed. in order to have more applicability, we have made a lot of adaptation, recursion and other knowledge are used. If you don't understand it for the moment, it doesn't matter. You just need to know how to use it. The above code can be directly applied to actual development. Remember, when you need to save too many States, you just need to think of this piece of code.

There are several other methods for self-execution of functions, such! Function () {} (), + function (){}()

Ii. function parameter transfer method: pass by value

Do you still remember the differences between the basic data type and the reference data type in replication? The basic data type Replication involves the replication of Direct values. Therefore, the changes do not affect each other. However, the reference data type is copied by the reference stored in the variable object. Therefore, the two references after the copy actually access the value in the same heap memory. When one of them is changed, the other is naturally changed. For example.

var a = 20;var b = a;b = 10;console.log(a);  // 20var m = { a: 1, b: 2 }var n = m;n.a = 5;console.log(m.a) // 5

When the value is passed into the function as a function parameter, the same difference exists. We know that after entering the function, the function parameters are actually saved in the variable object of the function. Therefore, this is equivalent to a copy. For example.

var a = 20;function fn(a) {    a = a + 10;    return a;}console.log(a); // 20
var a = { m: 10, n: 20 }function fn(a) {    a.m = 20;    return a;}fn(a);console.log(a);   // { m: 20, n: 20 }

It is precisely because of these differences that many people are confused when understanding how function parameters are transmitted. Is it passed by value or by reference? In fact, the conclusion is still passed by value, but when we expect to pass a reference type, it is actually passed, but this reference type is saved in the reference of the variable object. To illustrate this problem, let's look at the example below.

Var person = {name: 'nicholas ', age: 20} function setName (obj) {// input a reference obj = {}; // point the passed reference to another value obj. name = 'greg '; // modify the referenced name attribute} setName (person); console. log (person. name); // Nicholas has not been changed

In the above example, if the person is passed by reference, then the person will be automatically changed to a new object pointing to its name attribute value as Gerg. However, we can see from the results that the person object has not changed, so it is only modified in the internal reference of the function.

Iii. Functional Programming

Although JavaScript is not a pure functional programming language, it uses many functional programming features. Therefore, understanding these features gives us a better understanding of the code we write.

Function is the first citizen

The so-called "first class" refers to a function that is equal to other data types and can be assigned to other variables or used as a parameter to pass in another function, or return values of other functions. We have seen many of these scenarios.

Var a = function foo () {}// assign a value to function fn (function () {}, num) {}// function as the parameter // function as the return value function var () {return function (){......}}

Use only "expressions" and not "statements"

"Expression" (expression) is a simple operation and always has a return value. "statement" (statement) is an operation that does not return a value. Functional programming requires that only expressions are used, and no statements are used. That is to say, each step is a simple operation and has a return value.

Understanding this helps us develop good habits when encapsulating functions. With this feature, it is also a very important habit to understand the return values of functions when learning other APIs.

No "Side effects"

Side effect refers to the internal and external interactions between the function (the most typical case is to modify the value of the global variable) and generate operations other than the result.

Functional programming emphasizes no "Side effects", which means that the function must be independent. All functions return a new value without any other behavior, especially the value of external variables.

That is to say, as long as the same parameter is passed in, the returned results must be equal.

Closure

Closure is an important feature of functional programming languages. I have mentioned a lot about closure in the previous articles. I will not go into details here.

Kerihua

It is a little difficult to understand kerihua. I will analyze it in the next article separately.

Iv. Function Encapsulation

When we encapsulate functions ourselves, it is best to write them according to the features of functional programming. Of course, it cannot be fully implemented in many cases. For example, we often use private variables in modules in functions.

Common Encapsulation

function add(num1, num2) {    return num1 + num2;}add(20, 10); // 30

Attached to an object

if(typeof Array.prototype.add !== 'function') {  Array.prototype.add = function() {    var i = 0,        len = this.length,        result = 0;    for( ; i < len; i++) {        result += this[i]    }    return result;  }}[1, 2, 3, 4].add() // 10

An example of modifying an array object is often asked during interviews, but it is not recommended to extend the native object in actual development. Unlike General encapsulation, because we can use this to access the attributes and methods of objects mounted on the object prototype, this Encapsulation has many difficulties in actual use, therefore, we must master this.

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.