-
Notifications
You must be signed in to change notification settings - Fork 894
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
第 15 题:实现 add(1)(2)(3) #21
Comments
考点:函数柯里化 函数柯里化概念: 柯里化(Currying)是把接受多个参数的函数转变为接受一个单一参数的函数,并且返回接受余下的参数且返回结果的新函数的技术。 1)粗暴版 function add (a) {
return function (b) {
return function (c) {
return a + b + c;
}
}
}
console.log(add(1)(2)(3)); // 6 2)柯里化解决方案
const curry = (fn) =>
(judge = (...args) =>
args.length === fn.length
? fn(...args)
: (...arg) => judge(...args, ...arg));
const add = (a, b, c) => a + b + c;
const curryAdd = curry(add);
console.log(curryAdd(1)(2)(3)); // 6
console.log(curryAdd(1, 2)(3)); // 6
console.log(curryAdd(1)(2, 3)); // 6
function add (...args) {
//求和
return args.reduce((a, b) => a + b)
}
function currying (fn) {
let args = []
return function temp (...newArgs) {
if (newArgs.length) {
args = [
...args,
...newArgs
]
return temp
} else {
let val = fn.apply(this, args)
args = [] //保证再次调用时清空
return val
}
}
}
let addCurry = currying(add)
console.log(addCurry(1)(2)(3)(4, 5)()) //15
console.log(addCurry(1)(2)(3, 4, 5)()) //15
console.log(addCurry(1)(2, 3, 4, 5)()) //15 |
function currying(){
let args = [...arguments]
temp.getValue = ()=>{
return args.reduce((a,b)=> a + b, 0)
}
function temp(...arg){
if(arg.length){
args = [
...args,
...arg
]
return temp
}
}
return temp
} |
const add = (a: number, b: number, c: number) => a + b + c;
const adding = (...args: number[]) => args.reduce((pre, cur) => pre + cur, 0);
//参数确定
const curry = (fn: Function) => {
let args = [];
return function temp(...newArgs) {
args.push(...newArgs);
if (args.length === fn.length) {
const val = fn.apply(this, args);
args = [];
return val;
} else {
return temp;
}
};
};
//参数不确定
const currying = (fn: Function) => {
let args = [];
return function temp(...newArgs) {
if (newArgs.length) {
args.push(...newArgs);
return temp;
} else {
const val = fn.apply(this, args);
args = [];
return val;
}
};
};
const curryAdd = curry(add);
console.log(curryAdd(1)(2)(3)); // 6
console.log(curryAdd(1, 2)(3)); // 6
console.log(curryAdd(1)(2, 3)); // 6
let addCurry = currying(adding);
console.log(addCurry(1)(2)(3)(4, 5)()); //15
console.log(addCurry(1)(2)(3, 4, 5)()); //15
console.log(addCurry(1)(2, 3, 4, 5)()); //15 |
function curring(fn,arr = []){
var length = fn.length;
return (...args) => {
const currentArr = [...arr.push(args)]
if(arr.length < length){
return curring(fn,currentArr];
} else {
fn(...currentArr )
}
}
} |
function currying(fn, args = []) {
return function temp(...innerArgs) {
if (innerArgs.length > 0) {
// 收集后面传入的参数
args = [...args, ...innerArgs];
// 返回函数供后面可以继续调用
return temp;
} else {
const val = fn.apply(this, args);
// 清空参数数组,为了保证下次执行函数可以继续迭代
args = [];
return val;
}
}
}
// 求和函数
const add = (...args) => args.reduce((a, b) => a + b);
let addCurry = currying(add)
console.log(addCurry(1)(2)(3)(4, 5)()) //15
console.log(addCurry(1)(2)(3, 4, 5)()) //15
console.log(addCurry(1)(2, 3, 4, 5)()) //15 |
除了typeof为function 正常运算都没问题 |
有个疑问,就是参数长度不固定时,addCurry(1)(2)(3)(4, 5)(),最后的需要加函数执行的(),但是题目不是没有吗,也就是只要addCurry(1)(2)(3)(4, 5)这样 |
|
function add (...params) {
let result = params.reduceRight((a, b) => a + b)
const tmp = (...paramsInit) => {
result = [...paramsInit, result].reduceRight((a, b) => a + b)
return tmp
}
tmp.toString = () => `${result}`
tmp.valueOf = () => result
return tmp
} 可以这样实现 |
const curryAdd = (...args) => {
const Add = (...args2) => {
return curry(...args, ...args2)
}
Add.toString = () => args.reduce((t, v) => t+v);
return Add
}
console.log(curryAdd(1)(2)(3,4)) |
function curry(fn, args) {
var length = fn.length;
args = args || [];
return function () {
newArgs = args.conct(Array.prototype.slice.call(arguments));
return newArgs.length < length
? curry.call(this, fn, newArgs)
: fn.apply(this, newArgs);
};
}
function multiFn(a, b, c) {
return a * b * c;
}
var multi = curry(multiFn);
console.log(multi(2)(3)(4)); |
const sum = (arr) => { function add() { function newAdd() { newAdd.valueOf = function () { newAdd.toString = function () { return newAdd var result = add(1, 2)(3)(4)(5); // 参数可能为多个的情况下 console.log(result()); |
function curry(fn, args) {
const { length } = fn;
const params = args || [];
return function() {
const args = params.concat([].slice.call(arguments));
if (args.length < length) {
return curry.apply(this, fn, args);
} else {
return fn.apply(this, args);
}
}
} |
const curry = (fn) => {
const prevArgs = [];
const rec = (...currArgs) => {
prevArgs.push(...currArgs);
if(fn.length - prevArgs.length <= 0) {
return fn(...prevArgs);
}
return rec;
}
return rec;
}
const add = (a: number, b: number, c: number) => a + b + c;
const curryAdd = curry(add); |
函数的柯里化的应用 const curry = (fn, args) => {
const length = fn.length;
let _args = args || [];
return function () {
let argArray = _args.slice(0);
for (let i = 0; i < arguments.length; i++) {
argArray.push(arguments[i]);
}
if (argArray.length < length) {
return curry(fn, argArray);
} else {
return fn.apply(this, argArray);
}
}
}
const add = curry(function (a, b, c) {
return a + b + c;
})
console.log(add(1)(2)(3)); |
const add = a => b => c => a + b + c |
function curry(fn) { |
function curry(...args1) {
const fn = args1[0]
const restArgs = args1.slice(1)
function curried(...args2) {
return curry.call(this, fn, ...[...restArgs, ...args2])
}
curried.toString = function() {
return fn.call(this, ...restArgs)
}
return curried
}
function sum(...args) {
let result = 0
args.forEach(arg => {
result += arg
})
return result
}
const add = curry(sum)
// toString 修改了但是不生效,需要自己利用 + 操作符进行转换
console.log(+add(1)(2)(3, 4, 5)) |
暴力写法function add(a) {
return function (b) {
return function (c) {
return a + b + c;
};
};
}
console.log(add(1)(2)(3)) 如果不限调用3次呢,比如add(1)(2)(3)(4)返回8// 通过返回一个拥有获取值方法的函数
function add(x) {
let sum = x;
function innerAdd(y) {
sum += y;
return innerAdd;
}
innerAdd.getResult = function () {
return sum;
};
return innerAdd;
}
console.log(add(1)(2)(3)(4).getResult()); // 输出 10
// 缺点:获取值时需要额外调用.getResult() 题目没说add(1)(2)(3)就是返回值了,有没有可能是类里的方法class MyNumber {
constructor(value) {
this.value = value;
}
add(num) {
this.value += num;
return this.add.bind(this);
}
}
const myNum = new MyNumber(0);
myNum.add(1)(2)(3);
console.log(myNum.value); 函数柯里化// Function.length返回函数必传参数的长度
const curry = (fn) => {
return function curried(...args) {
if (args.length >= fn.length) {
return fn(...args);
} else {
return function (...nextArgs) {
return curried(...args, ...nextArgs);
};
}
};
};
const baseAdd = (a, b, c) => a + b + c;
const add = curry(baseAdd);
console.log(add(1)(2)(3)); // 6
console.log(add(1, 2)(3)); // 6
console.log(add(1)(2, 3)); // 6
console.log(add(1, 2, 3)); // 6
console.log(add(1)(2)); // 返回方法
try {
console.log(add(1)(2)(3)(4)); // 报错
} catch (error) {
console.error(error);
}
// 缺点,baseAdd长度写死,比暴力好在修改baseAdd更简单 不限长度的函数柯里化const infiniteCurry = (fn) => {
let lastArgsLength = 0;
return function curried(...args) {
if (args.length === lastArgsLength) {
return fn(...args);
} else {
lastArgsLength = args.length;
return function (...nextArgs) {
return curried(...args, ...nextArgs);
};
}
};
};
const infiniteAdd = (...args) => {
return Array.from(args).reduce((a, b) => a + b);
};
const add = infiniteCurry(infiniteAdd);
console.log(add(1)(2)());
console.log(add(1)(2)(3)());
console.log(add(1)(2)(3)(4)());
console.log(add(1, 2, 3)(4, 5)());
console.log(add(1, 2, 3, 4, 5, 6)());
// 缺点:获取值时要() |
欢迎在下方发表您的优质见解
The text was updated successfully, but these errors were encountered: