1、简述
高阶函数似乎是一种先进编程的的技术。然而,并不是。
高阶函数其实就是将函数作为参数或者返回值的函数。其中作为参数的函数一般是回调函数。
2、例子
(1)最简单的例子
大家都熟悉数组的sort方法。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>高阶函数</title>
</head>
<body>
<script type="text/javascript">
let arr = [1,2,4,3];
arr.sort((a,b)=>{return a-b})
console.log(arr)
</script>
</body>
</html>
sort方法的参数就是一个函数(回调函数),这个回调函数决定了如何比较数组中的任意两个元素。
Array的sort方法源码实现(使用了插入排序和快速排序):
function ArraySort(comparefn) {
// 使用款速排序算法
// 对于长度小于22的数组,使用插入排序算法
//判断comparefn是不是一个函数
var custom_compare = IS_FUNCTION(comparefn);
function Compare(x, y) {
// 假设comparefn(若存在的话)是一致的比较函数。
// 如果不是,则假设假设comparefn函数是任意的(通过ECMA 15.4.4.11)
if(x === y) return 0;
if(custom_compare) {
// 不要直接调用comparefn以避免暴露内置的全局对象。.
return comparefn.call(null, x, y);
}
x = ToString(x);
y = ToString(y);
if(x == y) return 0;
else return x < y ? -1 : 1;
};
//插入排序
function InsertionSort(a, from, to) {
for(var i = from 1; i < to; i ) {
var element = a[i];
// Pre-convert the element to a string for comparison if we know
// it will happen on each compare anyway.
var key =
(custom_compare || % _IsSmi(element)) ? element : ToString(element);
// place element in a[from..i[
// binary search
var min = from;
var max = i;
// The search interval is a[min..max[
while(min < max) {
var mid = min ((max - min) >> 1);
var order = Compare(a[mid], key);
if(order == 0) {
min = max = mid;
break;
}
if(order < 0) {
min = mid 1;
} else {
max = mid;
}
}
// place element at position min==max.
for(var j = i; j > min; j--) {
a[j] = a[j - 1];
}
a[min] = element;
}
}
//快速排序
function QuickSort(a, from, to) {
// 若数组长度小于22的话,使用插入排序。
if(to - from <= 22) {
InsertionSort(a, from, to);
return;
}
var pivot_index = $floor($random() * (to - from)) from;
var pivot = a[pivot_index];
// Pre-convert the element to a string for comparison if we know
// it will happen on each compare anyway.
var pivot_key =
(custom_compare || % _IsSmi(pivot)) ? pivot : ToString(pivot);
// Issue 95: Keep the pivot element out of the comparisons to avoid
// infinite recursion if comparefn(pivot, pivot) != 0.
a[pivot_index] = a[from];
a[from] = pivot;
var low_end = from; // Upper bound of the elements lower than pivot.
var high_start = to; // Lower bound of the elements greater than pivot.
// From low_end to i are elements equal to pivot.
// From i to high_start are elements that haven't been compared yet.
for(var i = from 1; i < high_start;) {
var element = a[i];
var order = Compare(element, pivot_key);
if(order < 0) {
a[i] = a[low_end];
a[low_end] = element;
i ;
low_end ;
} else if(order > 0) {
high_start--;
a[i] = a[high_start];
a[high_start] = element;
} else { // order == 0
i ;
}
}
QuickSort(a, from, low_end);
QuickSort(a, high_start, to);
}
var old_length = ToUint32(this.length);
if(old_length < 2) return this;
%
RemoveArrayHoles(this);
var length = ToUint32(this.length);
// 将未定义的元素移动到数组的末尾.
for(var i = 0; i < length;) {
if(IS_UNDEFINED(this[i])) {
length--;
this[i] = this[length];
this[length] = void 0;
} else {
i ;
}
}
QuickSort(this, 0, length);
//如果this是一个数组,我们只改变了这个数组的长度。 如果this不是数组,则不允许设置此对象的长度,因为这可能会引入新的length属性。
if(IS_ARRAY(this)) {
this.length = old_length;
}
return this;
}
(2)字符换大写
实现一:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>高阶函数</title>
</head>
<body>
<script type="text/javascript">
let arr = ['abc', 'def'],
arrNew = [];
for(let i = 0; i < arr.length; i ) {
arrNew[i] = arr[i].toUpperCase()
}
console.log(arrNew)
</script>
</body>
</html>
实现二:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>高阶函数</title>
</head>
<body>
<script type="text/javascript">
let arr = ['abc', 'def'],
arrNew = [];
arrNew = arr.map(val => {
return val.toUpperCase()
})
console.log(arrNew)
</script>
</body>
</html>
(3)高阶函数实现
若代码中出现重复或者类似的代码,就可以使用高阶函数。如产生一个包含数字的字符串:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>高阶函数</title>
</head>
<body>
<script type="text/javascript">
let digits = ''
for (let i=0;i<10;i ) {
digits = i
}
console.log(digits)
</script>
</body>
</html>
使用高阶函数实现:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>高阶函数</title>
</head>
<body>
<script type="text/javascript">
let digits = ''
function buildString(n, callback) {
let val = '';
for(let i = 0; i < n; i ) {
val = callback(i)
}
return val
}
digits = buildString(10, i => {
return i
})
console.log(digits)
</script>
</body>
</html>
更多专业前端知识,请上 【猿2048】www.mk2048.com