一、概念
- 函数可以作为参数被传递
- 函数可以作为返回值输出
二、应用场景
2.1 函数作为参数被传递
- 回调函数
// 经典回调 ajax异步请求
var getUserInfo = function(userId, callback) {
$.ajax('http://xxx.com/getUserInfo?' + userId, function(data) {
if(typeof callback === 'function') {
callback(data)
}
});
getUserInfo(123, function(data) {
console.log(data.userName);
});
}
- Array.prototype.sort
Array.prototype.sort 接收一个函数当参数,这个函数里面封装了数组元素的排序规则。
// 从小到大排列
[1, 4, 3].sort(a, b)=> a - b; // 输出 [1, 3, 4]
// 从大到小排列
[1, 4, 3].sort(a, b)=> b - a; // 输出 [4, 3, 1]
2.2 函数作为返回值输出
相比把函数当做参数传递,函数当做返回值输出的场景也许更多,也更能体现函数式编程的巧妙。让函数继续返回一个可执行的函数,意味着运算过程是可延续的。
- 判断数据的类型
var Type = {};
for(var i = 0, type; type = ['String, Array, Number']; [i++];) {
(function(type){
Type['is' + type] = function(obj) {
return Object.prototype.toString.call(obj) === '[object' + type +']';
}
})(type)
};
Type.isArray([]); // true
Type.isString('str'); // true
- getSingle 单列模式
var getSingle = function(fn) {
var ret;
return function() {
return ret || (ret = fn.apply(this, arguments));
};
};
这个高阶函数的例子,即把函数当做参数传递,又让函数执行后返回了另外一个函数。我们可以看看 getSingle 函数的效果:
var getScript = getSingle(function() {
return document.createElement('script');
});
var script1 = getScript();
var script2 = getScript();
console.log(script1 === script2); // true
2.3 高阶函数的其他应用
- 高阶函数实现AOP (面向切面编程)
- currying 函数柯里化
- uncurrying 反柯里化
- 节流函数
- 分时函数
- 惰性加载函数
...
三、最后
在JavaScript开发中,闭包和高阶函数应用极多。就设计模式而言,因为JavaScript这门语言的自身特点,许多设计模式在JavaScript之中的实现跟现在一些传统面向对象语言中的实现相差很大,在JavaScript中,很多设计模式都是通过闭包和高阶函数实现的。这并不奇怪,相对于模式的实现过程,我们更关心的是模式可以帮助我们完成什么。