Are you in? It should be. by the way, there's no six pulse sword here, or even it can't compete with the six pulse sword. But the title of this blog post is called this. It's not changed. What's more?
Back to the main topic, the functions in javascript are curried, and many articles on the Internet are written in various ways, even with fancy skills. (it's rarely used in practical work) the author looked at some of them. I thought I knew about it, but it became more and more confused. So I spent some time to sort them out, hoping to help you.
Authoritative sources
function currying, which is used to create a function with one or more parameters set. The basic method of function currification is the same as function binding: use a closure to return a function. The difference between the two is that when a function is called, the returned function also needs to set some incoming parameters.
function add(num1, num2){ return num1 + num2; } function curriedAdd(num2){ return add(5, num2); } alert(add(2, 3)); //5 alert(curriedAdd(3)); //8
This code defines two functions: add() and curiedadd(). The latter is essentially the add () version with the first parameter of 5 in any case. Although curiedadd () is not technically a curried function, it shows its concept well.
The curly function is usually created dynamically by calling another function and passing in the function to be curly and the necessary parameters for it. The following is a general way to create curried functions.
function curry(fn){ var args=Array.prototype.slice.call(arguments, 1); return function(){ var innerArgs=Array.prototype.slice.call(arguments); var finalArgs=args.concat(innerArgs); return fn.apply(null, finalArgs); }; }
The above content comes from "javascript advanced programming" Redbook.
Note that the bold part curiedadd() is not a currifying function
Expanding A
Source one
For an interview question, please implement a Coriolis function
Then the original blog posted such a code
const curry = (fn, ...args1) => (...args2) => ( arg => arg.length === fn.length ? fn(...arg) : curry(fn, ...arg) )([...args1, ...args2]); // call const foo = (a, b, c) => a * b * c; curry(foo)(2, 3, 4); // -> 24 curry(foo, 2)(3, 4); // -> 24 curry(foo, 2, 3)(4); // -> 24 curry(foo, 2, 3, 4)(); // -> 24
Seeing the above code, I have to use the "horizontal groove" arrow function to simplify the function writing. I am a bit confused by the continuous three arrows above. Who passed the parameters in brackets at last? Make it look better
const curry = function(fn, ...args1){ return function (...args2) { return function(arg){ return arg.length === fn.length ? fn(...arg) : curry(fn, ...arg) }([...args1, ...args2]); } }
The general-purpose korilization function is just the return function in the function. This is the return function in the function. The function in the function returns another function. The most internal function is called directly in the intermediate function.
The principle of this universal curry function is similar to the recursive call, which judges the number of parameters. If the original function fn has 8 parameters, it will continue to call itself recursively as long as it passes less than 8 parameters. If it does, it will call the original function fn
Expanding B
Source two
An add method is implemented to make the calculation result meet the following expectations:
add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4)(5) = 15;
function add() { // At first execution, an array is defined to store all parameters var _args = Array.prototype.slice.call(arguments); // Declare a function internally, save ﹐ args and collect all parameter values with the characteristics of closure var _adder = function() { _args.push(...arguments); return _adder; }; // Using the property of toString implicit conversion, when the last execution, implicit conversion is performed, and the final value return is calculated _adder.toString = function () { return _args.reduce(function (a, b) { return a + b; }); } return _adder; }
The above content code is completely quoted from "source 2". Here is my personal experiment:
It's a bit interesting, but when we call it in the following way, it really works
console.log("add(1)(2)(3):",add(1)(2)(3)); console.assert(add(2, 6)(1)!=9, "add(2, 6)(1)!=9"); console.log(add(1, 2, 3)(4)=="10") console.log(add(1, 2, 3)(4)==10) console.log(add(1, 2, 3)(4)==="10")
The output result is:
add(1)(2)(3): 6
Assertion failed: add(2, 6)(1)!=9
true
true
false
It seems not too strict. add is obviously a function. If it is called, what it returns is actually an internal function. However, this internal function rewrites toString to get the expected value at some default transformations. Corresponding to it is valueOf
Add the following code to the original add function
_adder.valueOf = function () { return 0; }
So, what do you think is the output of the following code?
console.log(add(1, 2, 3)(4)) console.log("hello boy:",add(1, 2, 3)(4)) console.log(add(1, 2, 3)(4)=="10") console.log(add(1, 2, 3)(4)==10)
... thinking
The results of the four lines are as follows:
{ [Function: _adder] toString: [Function], valueOf: [Function] }
hello boy: 10
false
false
----Is there a surprise?
therefore
Is there any harvest