函数柯里化
把使用多个参数的函数转换成一系列使用一个参数的函数,返回接受余下参数并且返回结果的新函数;(也就是:只传递一个部分参数来调用这个函数,让他返回一个新函数去处理余下的参数)
日常应用
- 动态创建函数:(dom元素添加事件监听是,根据兼容性判断生成不同的函数)
//只在函数第一次执行时判断一次,用到了闭包和立即执行函数
const addEvent = (function(){
if(window.addEventListener) {
return function(el, type, fn, capture){
el.addEventListener(type, fn, capture)
}
} else if(window.attachEvent) {
return function(el, type, fn) {
el.attachEvent('on' + type, fn)
}
}
})()
- 延迟计算:(调用方法传入参数,不计算最后结果,当不传任何值以后再计算)
const adds = function(...args) {
return args.reduce(function(a, b){ return a + b})
}
function currying2(func) {
let sum = [];
return function result() {
var arg = [].slice.call(arguments);
if(arg.length == 0) {
var res = func.apply(null,sum)
console.log('method2:' + res)
return res;
} else {
sum.push(...arg)
return result
}
}
}
let sum2 = currying2(adds);
let addCurryTwo = sum2(1,2)(3);
addCurryTwo(2)(); // 8
- 延时计算(指定传入的参数数量,满足后执行计算)
function currying1(fn, length) {
//fn.length获取的是函数形参的个数,第一个具有默认值之前的参数个数
length = length || fn.length; // 第一次是获取参数个数,之后是获取每次剩余参数个数
return function (...args) { //返回一个函数
if(args.length >= length){ // 当获取了全部数量的参数后,执行fn方法
// console.log(args);
return fn.apply(this, args);
} else {
return currying1(fn.bind(this, ...args), length - args.length) // 不满足函数个数,递归调用currying1方法,
}
}
}
// 计算方法
const fn = currying1(function(a, b, c) {
console.log([a, b, c]);
});
fn("a", "b")("c") // ["a", "b", "c"]
fn("a")("b")("c") // ["a", "b", "c"]
fn("a")("b", "c") // ["a", "b", "c"]
- 参数复用
判读一个数据的类型
function isType(type){
return function(arg){
var res = Object.prototype.toString.call(arg);
console.log(res)
return res == "[object "+ type +"]"
}
}
var res = isType('String')(null);
调用toString可以获取每个对象的类型,但是不同的对象有不同的toString的实现,所以要调用Object.prototype.toString()方法。
可以通过bind方法扩展,通过参数复用,实现一个toStr方法:
//使用函数的call方法指定一个this值,然后bind返回一个新函数,始终将Object.prototype.toString作为传入的参数
const toStr = Function.prototype.call.bind(Object.prototype.toString);
toStr([1,2,3]) ; //'[object Array]'
bind方法
- 返回一个指定上下文的函数
- 传入bind的第二个以及之后的参数,加上绑定函数运行时本身的参数, 按照顺序作为原函数的参数来调用原函数
var value = 2;
var foo = {
value: 1
};
function bar(name,age) {
return {
value:this.value,
name,
age
}
}
var bindFoo = bar.bind(foo, 'tommy').bind(foo, 23);
console.log(bindFoo()) // {value: 1, name: 'tommy', age: 23}