应用场景:一个函数拥有多个参数,且频繁调用,且前几个参数相对固定,使用柯里化固定函数前面的参数
为什么会有多个参数,且前几个参数又是相对固定的?
个人猜测:可能是某一个库比较灵活,很多功能都可以用到它,而前面几个参数可能就是划分类的,做到适配
实现
function kelihua(fn, ...args) {
return function (...subArgs) {
let newArgs = [...args, ...subArgs];
if (newArgs.length == fn.length) {
return fn(...newArgs);
} else {
console.log(newArgs)
return kelihua(fn, ...newArgs)
}
}
}
function calc(a, b, c, d) {
console.log("calc")
return a + b * c - d
}
console.log(calc.length)
var fn1 = kelihua(calc, 1, 2)
var fn2 = fn1(3)
console.log(fn2(4))
笔记
- function.length是参数的长度
- 柯里化函数的参数在return function后形成闭包,不需要另外保存
- 函数的执行需要满参数
- 对第二次柯里化操作,两次参数在递归调用一次后再次形成闭包保存
bind直接柯里化
var cate = {}
var ds1 = calc.bind(cate, 2, 3).bind(cate,4).bind(cate,5)
ds1()
上面链式写法是可以的,也可以逐级拆分
bind是Function.prototype的函数,所以由Function生成的function都能用bind这个方法
bind改变this指向的优先级小于new
bind生成的构造函数,用于new对象,对象保持原有的特性,bind不起作用
function original(x) {
this.a = 1;
this.b = function () { return this.a + x }
}
var obj1 = {
a: 10
}
var newObj = new (original.bind(obj1, 2)); //传入了一个实参2
console.log(newObj.a); //输出1, 说明返回的函数用作构造函数时obj(this的值)被忽略了
console.log(newObj.b()); //输出3 ,说明传入的实参2传入了原函数original
Function.prototype.myBind
细微差别,两种写法都能满足一定的功能
Function.prototype.myBind1 = function () {
var args = Array.prototype.slice.call(arguments, 1)
var obj = arguments[0]
var that = this
return function () {
var subArgs = Array.prototype.slice.call(arguments)
var newArgs = args.concat(subArgs)//concat不改变原数组
console.log(newArgs)
return that.apply(obj, newArgs)
}
}
Function.prototype.myBind2 = function (obj, ...args) {
const that = this
return function (...subArgs) {
let newArgs = [...args, ...subArgs]
console.log(newArgs)
if (that.length <= newArgs.length) {
return that.apply(obj, newArgs)
} else {
return callee(obj, newArgs)
}
}
}
var objs = {}
// var newfn = calc.myBind1(null, 1, 2).myBind1(null, 3).myBind1(null, 4)
var newfn = calc.myBind2(null, 1, 2).myBind2(null, 3).myBind2(null, 4)
newfn()
补充
fun.bind(obj)可以将一个函数剥夺给obj使用
fun.bind(obj)不会改变原来的函数,而是返回一个新的函数
在下例中,function先是运行了bind后,再赋给了fun
var objshadow = {value:14}
var obj = {
value:13,
fun:function(){
console.log(this.value);
}.bind(objshadow)
};
obj.fun()//14