所谓高阶函数,将函数作为参数或返回值的函数。将函数作为参数,通常又叫做回调函数。下面我们通过几个例子来理解一下高阶函数的定义。
函数作为参数
函数数组的sort方法
function compareNumber(x, y) {
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
}
[3, 1, 4, 1, 5, 9].sort(compareNumber); //[1, 1, 3, 4, 5, 9]
标准库需要传递一个具有compare的方法作为对象,这就是一个高阶函数。我们可以简化为匿名函数。
[3, 1, 4, 1, 5, 9].sort( function (x, y) {
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
}); //[1, 1, 3, 4, 5, 9]
掌握了这个方法,我们就可以用高阶函数简化自己的代码。需要引入高阶函数抽象的信号出现重复或相似的代码,例:
//生成a-z英文字母构造的字符串
var aIndex = 'a'.charCodeAt(0);//97
var alphabet = '';
for(var i = 0; i < 26; i++) {
alphabet += String.fromCharCode(aIndex + i);
}
alphabet//'abcdefghigklmnopqistuvwxyz'
//生成0-9的数字字符串
var digits = '';
for(var i = 0; i < 10; i++) {
digits += i;
}
digits//'0123456789'
//生成随机字符串
var random = '';
for(var i = 0; i < 8; i++) {
random += String.fromCharCode(Math.floor(Math.random()*26)+aIndex);
}
random//'bdwvfrtp'(different result each time )
我们可以看到虽然这三个函数的结果以及方法都不相同,但是我们不难发现,其中都用到了for循环以及累加的相似逻辑。所以我们可以提取相同的部分,简化函数
//提出公用的部分
function buildString(n, callback) {
var result = '';
for(var i = 0; i < n; i++) {
result += callback (i);
}
return result;
}
//简化上面的三个例子
var alphabet = buildString(26, function(i) {
return String.fromCharCode(aIndex + i);
})
var digits = buildString(10, function(i) {
return i;
})
var random = buildString(8, function(i) {
return String.fromCharCode(Math.floor(Math.random() * 26) + aIndex)
})
这样把高阶函数抽象出来
- 可以增加函数的可读性
- 更简洁,利于函数的维护
- 更高效,增强了函数的可扩展性
函数作为返回值
一个简单的惰性加载的案例,浏览器检测。比如返回顶部,我们需要区分火狐浏览器还是其他浏览器来决定scrollTop 的赋值。
// 一般的写法
var gotop = function(){
if(/firefox/i.test(navigator.userAgent)) {
document.documentElement.scrollTop = 0;
} else {
document.body.scrollTop = 0;
}
}
但是会有一个不完美的地方,当我们在代码中需要多处使用调用此函数的时候,我们每次都需要重新获取navigator.userAgent,然后进行判断,会多做一些无用功。所以我们进行一下改造
var gotop = (function(){
var isFF = /firefox/i.test(navigator.userAgent);
var docEl = document[ isFF ? 'documentElement' : 'body' ];
return function(){
docEl.scrollTop = 0;
}
})();
这样,改造完成之后,第一次进入浏览器的时候,浏览器的当前属性就已经赋值到gotop这个参数中并存储,当我们再次需要使用的时候,仅调用gotop这个参数就可以了不需要二次判断,提高了代码的效率。