Advanced Front-end BASICS (8): go deep into the corriization of functions

Source: Internet
Author: User
Curialization is a relatively advanced function application. It is not easy to understand it. Therefore, I have been thinking about how to make it easier for everyone to understand. After thinking for a long time, I decided to leave the Ke Lihua concept alone and add two important but easy-to-be-ignored knowledge points. Curialization is a relatively advanced function application. It is not easy to understand it. Therefore, I have been thinking about how to make it easier for everyone to understand. After thinking for a long time, I decided to leave the Ke Lihua concept alone and add two important but easy-to-be-ignored knowledge points.

1. implicit conversion of functions that supplement knowledge points

JavaScript is a weak type language, and its implicit conversion is flexible and interesting. If we do not have a deep understanding of implicit conversions, we may be confused about some calculation results, such as 4 + true = 5. Of course, if you have a deep understanding of implicit conversions, it is certainly able to greatly improve the ability to use JavaScript. I am not planning to share all the implicit conversion rules with you. Here I will only share some of the rules for implicit conversion of functions.

A simple question.

Function fn () {return 20;} console. log (fn + 10); // What is the output result?

Let's modify it a bit and then think about what the output result will be?

Function fn () {return 20;} fn. toString = function () {return 10;} console. log (fn + 10); // What is the output result?

You can continue to modify it.

Function fn () {return 20;} fn. toString = function () {return 10;} fn. valueOf = function () {return 5;} console. log (fn + 10); // What is the output result?
// The output result is function fn () {return 20;} 102015 respectively.

When console. log is used or an operation is performed, implicit conversion may occur. From the above three examples, we can draw some conclusions about Implicit Function Conversion.

When toString and valueOf are not redefined, the default toString method is called for implicit conversion of the function, and the defined content of the function is returned as a string. When the toString/vauleOf method is defined, the returned results of implicit conversion are controlled by ourselves. The priority of valueOf is a little higher than that of toString.

Therefore, the conclusion in the above example is easy to understand. We recommend that you try it.

2. Add knowledge points using the map method of the call/apply Array

Map (): runs a given function for each item in the array and returns an array composed of the results of each function call.

In general, it is to traverse every element of the array and return the calculation result after performing computation in the first parameter (callback function) of map. Returns a new array composed of all calculation results.

// The callback function has three parameters. // The first parameter indicates each item of newArr, the second parameter indicates the index value of the item in the array // The third parameter indicates the array itself // In addition, this in the callback function, when the map does not have the second parameter, this points to loss, if the second parameter exists, point to the object var newArr = [1, 2, 3, 4] set by the modified parameter. map (function (item, I, arr) {console. log (item, I, arr, this); // you can run return item + 1; // Add 1} for each item, {a: 1}) console. log (newArr); // [2, 3, 4, 5]

In the annotations in the above example, the details of the map method are described in detail. A challenge is how to encapsulate map.

You can first think about the for loop. We can use the for loop to implement a map, but we will consider some issues during encapsulation. When we use a for loop, a loop process is indeed well encapsulated, but what we want to do in the for loop is difficult to encapsulate with a fixed thing. In each scenario, the data processing in the for loop is certainly different.

So we thought of a good way to process these different operations with a single function, making this function the first parameter of the map method, the specific operations in this callback function are determined by our own usage. Therefore, the encapsulation implementation based on this idea is as follows.

Array. prototype. _ map = function (fn, context) {var temp = []; if (typeof fn = 'function') {var k = 0; var len = this. length; // encapsulate the for loop PROCESS for (; k <len; k ++) {// throw each operation into fn, use the call method to specify the this point of fn and the specific parameter temp. push (fn. call (context, this [k], k, this)} else {console. error ('typeerror: '+ fn +' is not a function. ');} // return the new array consisting of each calculation result return temp;} var newArr = [1, 2, 3, 4]. map (function (item) {return item + 1 ;}) // [2, 3, 4, 5]

In the above encapsulation, I first defined an empty temp array, which is used to store the final returned results. In a for loop, the fn function is executed once every cycle, and the fn parameter is passed in using the call method.

After understanding the encapsulation process of map, we can understand why we always expect a return value in the first callback function when using map. In eslint rules, if we do not set a return value when using map, it will be regarded as an error.

OK. Now that you understand the implicit conversion rules of the function and the usage of call/apply in this scenario, we can try to use a simple example to understand Keri.

Iii. Ke Lihua

In the front-end interview, there was an interview with ke Lihua, which was widely spread.

Implement an add method to meet the following expectations:

add(1)(2)(3) = 6add(1, 2, 3)(4) = 10add(1)(2)(3)(4)(5) = 15

Obviously, the calculation result is the sum of all parameters. Every time the add method runs, the same function is certainly returned and the remaining parameters are calculated.

We can find a solution step by step from the simplest example.

It can be encapsulated in this way when we only call it twice.

function add(a) {    return function(b) {        return a + b;    }}console.log(add(1)(2));  // 3

If only three times are called:

function add(a) {    return function(b) {        return function (c) {            return a + b + c;        }    }}console.log(add(1)(2)(3)); // 6

The above encapsulation seems to be a little similar to what we want, but the use of parameters is very limited, so it is not the final result we want, we need a general encapsulation. What should I do? To sum up the above two examples, we actually use the closure feature to aggregate all parameters into the final returned function for calculation and return results. Therefore, during encapsulation, the main purpose is to aggregate the parameters for calculation.

To see the specific implementation.

Function add () {// during the first execution, an array is defined to store all the parameters var _ args = []. slice. call (arguments); // declare a function internally, save _ args using the closure feature, and collect all parameter values var adder = function () {var _ adder = function () {[]. push. apply (_ args, []. slice. call (arguments); return _ adder;}; // use the implicit conversion feature to perform implicit conversion at the end of the execution and calculate the final value to return _ adder. toString = function () {return _ args. reduce (function (a, B) {return a + B;}) ;}return _ adder;} return adder. apply (null, []. slice. call (arguments);} // output result. You can freely combine the parameter console. log (add (1, 2, 3, 4, 5); // 15console. log (add (1, 2, 3, 4) (5); // 15console. log (add (1) (2) (3) (4) (5); // 15

The above implementation, using the closure feature, mainly aims to collect all the parameters in an array through some clever methods, and add all the items in the array during implicit conversion. Therefore, when we call the add method, the parameters are very flexible. Of course, it is easy to meet our needs.

So I read the demo above, and then let's take a look at the definition of colihua. I believe it will be easier for everyone to understand.

Currying, also known as partial evaluation, is a function that converts a function that accepts multiple parameters into a function that accepts a single parameter (the first parameter of the original function, and return a new function technology. The new function accepts the remaining parameters and returns the calculation result.

1. receive a single parameter. Because it carries a lot of information, it is often solved based on the callback function.

2. Pass some parameters to the function through callback functions and other methods.

3. Return a new function to process all parameters to be passed in.

In the preceding example, we can convert add (1, 2, 3, 4) to add (1) (2) (3) (4 ). This is part of the evaluation. Each input parameter is only part of all the parameters we want to pass in. Of course, in actual applications, it is not often so complicated to process parameters. In many cases, it is only divided into two parts.

Let's start by thinking about a problem related to colihua.

If there is a computing requirement, we need to connect each item in the array with the characters we want. What should we do? It is easy to think of using the join method.

Var arr = [1, 2, 3, 4, 5]; // In actual development, it is not recommended to extend the new method to the Array directly. // This method is only used to demonstrate a clearer Array. prototype. merge = function (chars) {return this. join (chars);} var string = arr. merge ('-') console. log (string); // 1-2-3-4-5

Increase the difficulty. Add one number for each item and then connect it. Here we need map to help us perform special operations on each item, generate a new array, and connect it with characters. The implementation is as follows:

var arr = [1, 2, 3, 4, 5];Array.prototype.merge = function(chars, number) {    return this.map(function(item) {        return item + number;    }).join(chars);}var string = arr.merge('-', 1);console.log(string); // 2-3-4-5-6

But what if we want to make each array subtract an array and connect it again? Of course, this is the same as the above addition operation.

var arr = [1, 2, 3, 4, 5];Array.prototype.merge = function(chars, number) {    return this.map(function(item) {        return item - number;    }).join(chars);}var string = arr.merge('~', 1);console.log(string); // 0~1~2~3~4

Witty friends must find their puzzles. We expect to encapsulate a function that can process different computing processes at the same time, but we cannot use a fixed routine to encapsulate each operation. The problem becomes the same as the problem encountered during map encapsulation. We can use ke Lihua to solve the problem.

Similar to map encapsulation, since we are not sure how we will process each item of data in advance, I just know that we need to process them and then connect them with characters, therefore, you may wish to save the processing content in a function. This part of the requirement is fixed and encapsulated.

So we have the following encapsulation.

// Encapsulation is very simple. Get Array in one sentence. prototype. merge = function (fn, chars) {return this. map (fn ). join (chars);} var arr = [1, 2, 3, 4]; // The difficulty lies in how to define the operation in actual use, save the closure to pass the num parameter var add = function (num) {return function (item) {return item + num;} var red = function (num) {return function (item) {return item-num ;}// add 2 for each item and merge var res1 = arr. merge (add (2), '-'); // merge var res2 = arr after each item is reduced by 2. merge (red (1), '-'); // You can also use the callback function to merge var res3 = arr. merge (function (num) {return function (item) {return item * num}) (2), '-') console. log (res1); // 3-4-5-6console.log (res2); // 0-1-2-3console.log (res3); // 2-4-6-8

Can you refer to the above example to find the characteristics of colitization?

Iv. Keri General

The general Keri writing method is actually much simpler than the add method encapsulated above.

Var currying = function (fn) {var args = []. slice. call (arguments, 1); return function () {// collect all required parameters into an array for Unified Calculation of var _ args = args. concat ([]. slice. call (arguments); return fn. apply (null, _ args) ;}} var sum = currying (function () {var args = []. slice. call (arguments); return args. reduce (function (a, B) {return a + B;})}, 10) console. log (sum (20, 10); // 40console. log (sum (10, 5); // 25

V. Keri and bind

Object.prototype.bind = function(context) {    var _this = this;    var args = [].prototype.slice.call(arguments, 1);    return function() {        return _this.apply(context, args)    }}

In this example, call and apply are used flexibly to implement the bind function.

In the previous examples, we can summarize the features of colihua:

1. receive a single parameter and use the callback function to handle more parameters?

2. Return a new function to process all parameters to be passed in;

3. parameters need to be collected using call/apply and arguments objects;

4. The returned function is used to process the collected parameters.

I hope that after reading this article, you will be able to understand the concept of colihua. If you want to use it skillfully, you need to have more practical experience.

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.