去年在过前端基础技术栈的时候有简单记录过一点高阶函数笔记 前端基础学习之js高级
在看js设计模式与开发实践的时候,第一章节都在讲一些基础,比如this、call、apply、闭包等等。在看到高阶函数的时候,有些高阶应用比如节流是比较常见的,而有一些高阶函数的应用之前没有了解过,比如currying、分时函数等等,个人而言比较新奇,记录一下子~
高阶函数
满足以下两种条件之一的函数即高阶函数
- 函数可以作为参数传递
- 函数可以作为返回值输出
高阶函数的应用
- 1.回调函数 - 作为参数传递 (之前笔记中有提到)
- 2.数组的sort方法 - 作为参数传递 (同上)
- 3.判断数据类型 -作为返回值输出
let Type={}
for(let i=0,type; type = ['String', 'Array', 'Number'][i++];){
(function (type) {
Type['is'+type] =function (obj) {
return Object.prototype.toString.call(obj) === '[object '+type+']'
}
})(type);
}
console.log(Type.isString('str'));//true
console.log(Type.isArray([]));//true
console.log(Type.isNumber(123));//true
console.log(Type.isNumber("23"));//false
- 4.单例模式 -作为返回值输出
let getSingle = function (fn) {
let ret;
return function () {
return ret || (ret=fn.apply(this,arguments))
}
}
let getDom=getSingle(function () {
return document.getElementsByTagName('div')
})
let dom1=getDom();
let dom2=getDom();
console.log(dom1 === dom2) // true
- 5.实现AOP --把一个函数动态植入另一个函数中
Function.prototype.before = function( beforefn ){
var __self = this; // 保存原函数的引用
return function(){ // 返回包含了原函数和新函数的"代理"函数
// console.log(this)
beforefn.apply( this, arguments ); // 执行新函数,修正 this
return __self.apply( this, arguments ); // 执行原函数
}
};
Function.prototype.after = function( afterfn ){
var __self = this;
return function(){
var ret = __self.apply( this, arguments );
afterfn.apply( this, arguments );
return ret;
}
};
var func = function(){
console.log( 2 );
};
func = func.before(function(){
console.log( 1 );
}).after(function(){
console.log( 3 );
});
func();// 1 2 3
- 6.currying 函数柯里化 – 首先接收一些参数,接收这些参数之后不会立即求值,而是返回另一个函数,当函数真正需要求值的时候,之前传入的参数会被一次性求值
let currying =function (fn) {
let args=[]
return function () {
if(arguments.length ===0){
//当没有传值之后,一起计算总值
return fn.apply(this,args)
}else {
//反之则只把参数存入args
[].push.apply(args,arguments)
return arguments.callee
}
}
}
let cost =(function () {
let money=0;
return function () {
for(let i=0,l=arguments.length;i<l;i++){
money +=arguments[i]
}
return money
}
})()
let costs =currying(cost)
console.log(costs(100));
console.log(costs(200));
console.log(costs(300));
console.log(costs(400));
console.log(costs());
- 7.uncurrying —没理解这个应用的作用o(╥﹏╥)o
Function.prototype.uncurrying=function () {
let _self=this
return function () {
console.dir(arguments)
//取出参数中的第一个,即要被调用的对象 [1,2,3]
let obj=Array.prototype.shift.call(arguments);
//剩下的就是后续的传参参数 4,5
return _self.apply(obj,arguments)
}
}
let push=Array.prototype.push.uncurrying();
(function () {
push(arguments,4,5);
console.log(arguments);
})(1,2,3)
- 8.函数节流 (以前的文章中有提过)
- 9.分时函数 --工作分批进行 --例如分批创建div
//参数 1.要处理的数据 2. 处理函数 3.每次处理数量
let timeChunk =function (data,fn,count) {
let obj, timer;
let start =function () {
for(let i=0;i<Math.min(count||1,data.length);i++){
let obj =data.shift();
fn(obj)
}
}
return function () {
timer=setInterval(function () {
if(data.length === 0){
return clearInterval(timer)
}
start()
},200)
}
}
let arr =[]
for(let i=1;i<=1000;i++){
arr.push(i)
}
let renderDivList=timeChunk(arr,function (n) {
let div=document.createElement('div');
div.innerHTML=n;
document.body.appendChild(div)
},8)
renderDivList()
- 10.惰性加载函数
let addEvent=function (ele,type,fn) {
if(window.addEventListener){
addEvent = function (ele, type, fn) {
ele.addEventListener(type,fn,false)
}
}else if(window.attachEvent){
addEvent= function () {
ele.attachEvent('on'+type,fn)
}
}
addEvent(ele,type,fn)
}