柯里化函数Currying
常见的柯里化函数bind,它只返回一个函数,实现如下:
Function.prototype.bindv2 = function() {
const fn = this;
const arr = [].slice.call(arguments);
const _this = arr[0];
arr.splice(0,1);
return function() {
return fn.apply(_this, [...arr, ...arguments])
}
}
function A() {
console.log(arguments, this.name);
}
A.bindv2(A,20)(30,20);
// Arguments(4) [80, 88, 77, 66, callee: ƒ, Symbol(Symbol.iterator): ƒ],'A'
完整的柯里化
function currying() {
let args = [].slice.call(arguments);
console.log(args);
function closure() {
args.push(...([].slice.call(arguments)))
console.log('--->', args);
return closure;
}
closure.toString = function() {
return args.reduce((sum, next) => {
sum = sum + next;
return sum;
}, 0);
}
return closure;
}
调用的时候,可以是:
var fn = currying(1,2,3)(4,5,6,7)(1)(2,3);
fn.toString(); // 调用了toString,返回所有相加结果
如果console.log(fn==40); // 此时也会隐式调用toString方法
toString与valueOf什么情况下先执行
如果没有重新定义valueOf和toString,其隐式转换会调用默认的toString()方法。如果重新定义了,那么其转换会按照定义的来。其中,valueOf比toString优先级更高。
valueOf() 和 toString() 在特定的场合下会自行调用
自己重写toString方法和valueOf方法之后, alert竟然先调用了toString再调用valueOf,发现toString不是原始值,就再调用valueOf
var obj = {
toString: function() {
console.log('调用了 obj.toString');
return {};
},
valueOf: function() {
console.log('调用了 obj.valueOf');
return '110';
}
}
alert(obj); // 调用了 obj.toString // 调用了 obj.valueOf // 110
Number 类型转换规则
- 调用 Number() 函数,强制进行 Number 类型转换
- 调用 Math.sqrt() 这类参数需要 Number 类型的方法
- obj == 1 ,类似这种需要进行对比的时候
- obj + 1 , 类似这种需要进行运算的时候
总结规则
- 如果 valueOf 存在,且返回原始类型数据,返回 valueOf 的结果。
- 如果 toString 存在,且返回原始类型数据,返回 toString 的结果。 其他情况,抛出错误
Boolean 转换
布尔比较时 if(obj) , while(obj) 等判断时
简单来说,除了下述 6 个值转换结果为 false,其他全部为 true:
- undefined
- null
- -0
- 0或+0
- NaN
- ''(空字符串)
Function 转换规则
尝试 Function和Number类似, 是先调用valueOf方法, 若valueOf方法返回的不是一个原始类型, 则调用toString方法, 若toString方法返回的也不是一个原始类型, 则报错
注意!!: 函数在执行的时候, 必定会自动调用valueOf方法或toString方法
总结
- 如果没有重新定义valueOf和toString,其隐式转换会调用默认的toString()方法。
- 如果只改写 valueOf() 或是 toString() 其中一个,会优先调用被改写了的方法
- 而如果两个同时改写,则会像 Number 类型转换规则一样,优先查询 valueOf() 方法,在 valueOf() 方法返回的是非原始类型的情况下再查询 toString() 方法 。