JavaScript Learning records day7-higher order functions
[TOC]
1. What is a higher order function
Higher-order functions are called Higher-order function in English. So what is a higher order function?
JavaScript functions actually point to a variable. Since the variable can point to a function, the function's arguments can receive the variable, then one function can receive another function as a parameter, which is called the higher order function.
One of the simplest high-order functions:
function add(x, y, f) { return f(x) + f(y);}
When we call add(-5, 6, Math.abs)
, arguments x
, y
and f
respectively receive -5
, 6
and function, according to the Math.abs
function definition, we can deduce the calculation process as:
x = -5;y = 6;f = Math.abs;f(x) + f(y) ==> Math.abs(-5) + Math.abs(6) ==> 11;return 11;
Verify with code:
‘use strict‘;function add(x, y, f) { return f(x) + f(y);}var x = add(-5, 6, Math.abs); console.log(x); // 11
2.
map
For example, if we have a function f(x)=x2
to function on an array [1, 2, 3, 4, 5, 6, 7, 8, 9]
, it can be map
implemented as follows:
Because the map()
method is defined in JavaScript Array
, we call Array
the map()
method, passing in our own function, and get a new Array
result:
‘use strict‘;function pow(x) { return x * x;}var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];var results = arr.map(pow);console.log(results); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
<font color= "Red" > Note </font>:
map()
The parameters passed in are, that is pow
, the function object itself.
Someone might think, no need map()
, write a loop, or you can calculate the result:
var f = function (x) { return x * x;};var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];var result = [];for (var i=0; i<arr.length; i++) { result.push(f(arr[i]));}
Yes, but, from the loop code above, we cannot see at a glance the f(x)
elements that are acting on Array
each element and generate a new Array
"result."
So, map()
as a higher-order function, in fact it abstracts the arithmetic rules, so we can not only calculate the simple f(x)=x2
, but also can calculate arbitrarily complex functions, for example, Array
all the numbers into a string:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];arr.map(String); // [‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘7‘, ‘8‘, ‘9‘]
Only one line of code is required.
3.
reduce
Again look at reduce
the usage. Array
of reduce()
a function on this Array
[x1, x2, x3...]
, the function must receive two parameters, the reduce()
results continue and the next element of the sequence to do the cumulative calculation, the effect is:
[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
For example, to a Array
sum, you can use the reduce
implementation:
var arr = [1, 3, 5, 7, 9];result = arr.reduce(function (x, y) { return x + y;});console.log(result); // 25
exercise : Using reduce()
quadrature:
function product(arr) { result = arr.reduce(function (x, y) { return x * y; }); return result;}// 测试:if (product([1, 2, 3, 4]) === 24 && product([0, 1, 2]) === 0 && product([99, 88, 77, 66]) === 44274384) { console.log(‘测试通过!‘);}else { console.log(‘测试失败!‘);}
To [1, 3, 5, 7, 9]
transform into integers 13579
, you reduce()
can also come in handy:
var arr = [1, 3, 5, 7, 9];arr.reduce(function (x, y) { return x * 10 + y;}); // 13579
If we continue to refine this example, find a way to turn a string 13579
into a Array
-- [1, 3, 5, 7, 9]
and then use reduce()
it to write a function that converts the string to number.
Practice :
Do not use the JavaScript built-in parseint () function to implement a string2int () function with the map and reduce operations:
‘use strict‘;function string2int(s) { // 利用js变量弱类型转换 var s_length = s.length; if (s_length == 1) { return s * 1; } else { var arr = s.split(""); var result = arr.reduce(function (x, y) { return x * 10 + y * 1; }); return result; }}// 测试:if (string2int(‘0‘) === 0 && string2int(‘12345‘) === 12345 && string2int(‘12300‘) === 12300) { if (string2int.toString().indexOf(‘parseInt‘) !== -1) { console.log(‘请勿使用parseInt()!‘); } else if (string2int.toString().indexOf(‘Number‘) !== -1) { console.log(‘请勿使用Number()!‘); } else { console.log(‘测试通过!‘); }}else { console.log(‘测试失败!‘);}
Practice :
Please change the user's non-standard English name into the first letter, the other lowercase canonical name. Input: [‘adam‘, ‘LISA‘, ‘barT‘]
, Output: [‘Adam‘, ‘Lisa‘, ‘Bart‘]
.
‘use strict‘;function normalize(arr) { // return arr.map((x)=>{ // if(x.length > 0) // { // x = x.toLowerCase(); // x = x[0].toUpperCase() + x.substr(1); // } // return x; // }); return arr.map(function (x) { return x.substring(0, 1).toUpperCase() + x.substring(1).toLowerCase(); });}// 测试:if (normalize([‘adam‘, ‘LISA‘, ‘barT‘]).toString() === [‘Adam‘, ‘Lisa‘, ‘Bart‘].toString()) { console.log(‘测试通过!‘);}else { console.log(‘测试失败!‘);}
Xiaoming wanted to use map () to turn the string into an integer, and the code he wrote was simple:
‘use strict‘;var arr = [‘1‘, ‘2‘, ‘3‘];var r;r = arr.map(parseInt);console.log(r);
As a result 1, NaN, NaN
, Xiao Ming is baffled, please help him find the reason and fix the code.
parseInt( ) 的语法:parseInt ( String s , [ int radix ] )其中,参数 String s ,必需,表示要被解析的字符串。int radix ,可选,表示要解析的数字的基数。该函数使用第二个参数指定的基数,其值介于 2 ~ 36 之间。如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。["1","2","3"].map(parseInt)等于[parseInt(1,0),parseInt(2,1),parseInt(3,2)];
4.
filter
filter
is also a common operation, it is used to Array
filter out some of the elements, and then return the remaining elements.
and map()
Similarly, Array
filter()
a function is also received. And the map()
difference is that the filter()
incoming function acts on each element in turn, and then whether true
false
the element is persisted or discarded based on the return value.
For example, in one Array
, delete an even number, keep only the odd number, and you can write:
var arr = [1, 2, 4, 5, 6, 9, 10, 15];var r = arr.filter(function (x) { return x % 2 !== 0;});console.log(r); // [1, 5, 9, 15]
To delete an empty string in an array, you can write:
var arr = [‘A‘, ‘‘, ‘B‘, null, undefined, ‘C‘, ‘ ‘];var r = arr.filter(function (s) { return s && s.trim(); // 注意:IE9以下的版本没有trim()方法});console.log(r); // [‘A‘, ‘B‘, ‘C‘]
filter()
the key to using this higher-order function is to implement a "filter" function correctly.
callback function
filter()
The received callback function can actually have multiple parameters. Usually we use only the first parameter, which represents an Array
element. The callback function can also receive two additional parameters, representing the location of the element and the array itself:
var arr = [‘A‘, ‘B‘, ‘C‘];var r = arr.filter(function (element, index, self) { console.log(element); // 依次打印‘A‘, ‘B‘, ‘C‘ console.log(index); // 依次打印0, 1, 2 console.log(self); // self就是变量arr return true;});
Using filter
, can subtly remove Array
the repeating elements:
‘use strict‘;var r, arr = [‘apple‘, ‘strawberry‘, ‘banana‘, ‘pear‘, ‘apple‘, ‘orange‘, ‘orange‘, ‘strawberry‘];r = arr.filter(function (element, index, self) { return self.indexOf(element) === index;});console.log(r.toString()); // apple,strawberry,banana,pear,orange
The removal of a repeating element relies on indexOf
always returning the position of the first element, and the subsequent repetition of the element's position is indexOf
not equal to the position returned, and is therefore filter
filtered out.
Practice
Try to filter()
filter out primes:
‘use strict‘;function get_primes(arr) { // 判断一个整数m是否为素数,只需用2至m-1之间的每一个整数去除,如果都不能被整除,那么m就是一个素数。 // 对于一个正整数m而言,它对(m/2, m)范围内的正整数是必然不能够整除的, // 因此,我们在判断m的时候,没有必要让它除以该范围内的数。 var r = arr.filter(function (element, index, self) { var i; var result = true; for (i = 2; i <= element / 2 ; i++) { if (element % i == 0) { result = false; break; } } return element < 2 ? false : result; }); return r;}// 测试:var x, r, arr = [];for (x = 1; x < 100; x++) { arr.push(x);}r = get_primes(arr);if (r.toString() === [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97].toString()) { console.log(‘测试通过!‘);} else { console.log(‘测试失败: ‘ + r.toString());}
5. Sorting Algorithms
Sorting is also an algorithm that is often used in programs. Whether you use bubble sorting or fast sorting, the core of the sort is to compare the size of the two elements. If it's a number, we can compare it directly, but what about a string or two objects? There is no point in directly comparing the size of mathematics, so the process of comparison must be abstracted by functions. It is generally stipulated that for two elements x and Y, if considered, then returned, if considered, then returned, x < y
-1
x == y
0
if thought x > y
, then returned, 1
so that the sorting algorithm does not care about the specific comparison process, but rather the direct ordering according to the comparison results.
JavaScript's Array
sort()
approach is for sorting, but the sort results can be a surprise to you:
// 看上去正常的结果:[‘Google‘, ‘Apple‘, ‘Microsoft‘].sort(); // [‘Apple‘, ‘Google‘, ‘Microsoft‘];// apple排在了最后:[‘Google‘, ‘apple‘, ‘Microsoft‘].sort(); // [‘Google‘, ‘Microsoft", ‘apple‘]// 无法理解的结果:[10, 20, 1, 2].sort(); // [1, 10, 2, 20]
The second sort apple
is ranked last because the strings are sorted according to the ASCII code, while a
the ASCII code of the lowercase letters is after the uppercase letters.
What is the third sort of result? Can a simple numeric order be wrong?
This is because Array
the sort()
method defaults to converting all the elements first to String
reorder, and the result is ‘10‘
in ‘2‘
front of it because the characters ‘1‘
‘2‘
are smaller than the ASCII code of the characters.
If you do not know sort()
the default collation of the method, sort the numbers directly, absolutely planted in the pit!
Fortunately, the sort()
method is also a higher-order function, and it can also receive a comparison function to implement a custom sort.
To sort by numerical size, we can write this:
‘use strict‘;var arr = [10, 20, 1, 2];arr.sort(function (x, y) { if (x < y) { return -1; } if (x > y) { return 1; } return 0;});console.log(arr); // [1, 2, 10, 20]
If you want to sort in reverse order, we can put the large number in front:
var arr = [10, 20, 1, 2];arr.sort(function (x, y) { if (x < y) { return 1; } if (x > y) { return -1; } return 0;}); // [20, 10, 2, 1]
By default, the string is sorted by the size of ASCII, and now we propose that the sort should be ignored in case, sorted alphabetically. To implement this algorithm, you do not have to change the existing code, as long as we can define the ignoring case of the comparison algorithm can be:
var arr = [‘Google‘, ‘apple‘, ‘Microsoft‘];arr.sort(function (s1, s2) { x1 = s1.toUpperCase(); x2 = s2.toUpperCase(); if (x1 < x2) { return -1; } if (x1 > x2) { return 1; } return 0;}); // [‘apple‘, ‘Google‘, ‘Microsoft‘]
Ignoring the case to compare two strings is actually the first to capitalize the strings (or all lowercase) before comparing them.
As you can see from the above example, the abstraction of higher-order functions is very powerful, and the core code can be kept very concise.
Finally, the sort()
method will be modified directly, Array
it returns the result is still the current Array
:
var a1 = [‘B‘, ‘A‘, ‘C‘];var a2 = a1.sort();a1; // [‘A‘, ‘B‘, ‘C‘]a2; // [‘A‘, ‘B‘, ‘C‘]a1 === a2; // true, a1和a2是同一对象
Learning Reference Tutorial: http://www.liaoxuefeng.com
JavaScript Learning records day7-higher order functions