This is the code
const func0 = (...args) => {
console.error('-------0-------');
console.error(args);
console.error(args.length);
func1(args);
}
const func1 = (...args) => {
console.error('-------1-------');
console.error(args);
console.error(args.length);
}
func0(1, 2, 3);
why the 2nd arg is different now, how to make it the same as 1st one ?
(...args) => in the parameter list transforms the arguments into an array named args. So when you call func1(args);, you're calling func1 with one argument, an argument that's an array (whereas func0 was called with three arguments).
If you wanted to call func1 with the three original arguments, use spread to transform the args array into a parameter list:
const func0 = (...args) => {
console.error('-------0-------');
console.error(args);
console.error(args.length);
func1(...args);
}
const func1 = (...args) => {
console.error('-------1-------');
console.error(args);
console.error(args.length);
}
func0(1,2,3);
Related
This question already has answers here:
TypeScript type signatures for functions with variable argument counts
(3 answers)
Closed last year.
I know theres probably an easy answer to this but I'm trying to create a function that resolves / returns the value of a variable amount of functions into an array. However it looks like typescript doesn't like this. What would be the appropriate way to write / fix this function
const func = (x:number, y:number) => {x,y}
const executeRepetitiveFunction = (num: number, func: () => unknown) => {
const returnValues: Array<(unknown)> = []
for (let i = 0; i < num; i++) {
returnValues.push(func())
}
return returnValues
}
error
var result = func();
^
TypeError: func is not a function
at executeRepetitiveFunction
If you want to return something from the function you are passing and store it in an array, you can just call it and declare func as a Function type.
You can do something like this:
const executeRepetitiveFunction = (num: number, func: Function) => {
const returnValues: Array<(unknown)> = []
for (let i = 0; i < num; i++) {
returnValues.push(func())
}
return returnValues
}
const testFunction: Function = (): String => {
return 'ok';
}
executeRepetitiveFunction(5, testFunction);
This will return ok 5 times and store it in an array . // Output: ['ok', 'ok', 'ok', 'ok', 'ok']
As someone said, your code doesn't make sense. The error you're seeing is completely accurate - you have no function defined called func. You have func set up as the name of a parameter in your executeRepetitiveFunction function declaration, but it's not available outside of that function's scope.
So that error is irrelevant to the question you're asking, and I'll just answer the question you're actually asking.
const executeRepetitiveFunction = (num: number, func: () => unknown) : Promise<Array<any>> => {
return new Promise((resolve, reject) => {
const returnValues: Array<any> = []
for (let i = 0; i < num; i++) {
returnValues.push(func())
}
resolve(returnValues);
});
}
const valuesPromise = executeRepetitiveFunction(5, () => {
return "Execution complete"
});
So what happens here? First we declare our executeRepetitiveFunction function, which takes two parameters, a number and a function which returns an unknown data type. Then we return a promise from this function, which resolves once the loop is complete.
We execute the function after it's declared, by calling the executeRepetitiveFunction function and passing it a number (5) and an anonymous function that simply returns a value.
Then when that's done, we can access our values by calling valuePromise.then(valuesArray => {console.log(valuesArray}); or handling it however else you want.
Instead of:
const fn = (ctx, a, ...rest) => {};
const fnCurried = (ctx) => (b) => (...rest) => fn(ctx, b, ...rest);
someFn("something", fnCurried(ctx));
I would like to be able to call "fn" at top level, so I thought maybe storing the context in another method would help, I have no idea how to go about doing this
const fnCurried = createCtx(ctx)
someFn("something", fnCurried(fn))
In your first example, someFn takes a second argument as a function of the form:
(b) => (...rest) => fn(ctx, b, ...rest);
In your second example, you want to keep this behaviour, this means calling fnCurried(fn) must return the above function. We can do this by writing:
const fnCurried = (fn) => (b) => (...rest) => fn(ctx, b, ...rest);
However, if we just use this, then we haven't supplied the context anywhere. That's where we can make another function called createCtx() that will return the above fnCurried function for us, while also closing over a supplied ctx:
const createCtx = ctx => fn => b => (...rest) => fn(ctx, b, ...rest);
const fnCurried = createCtx(ctx);
someFn("something", fnCurried(fn));
The createCtx function allows us to pass in the context, which then returns fnCurried for us, that can be passed into someFn once called
I have an arrow function that looks like this (simplified):
const f = arg => { arg.toUpperCase(); };
But when I call it, I get undefined:
console.log(f("testing")); // undefined
Why?
Example:
const f = arg => { arg.toUpperCase(); };
console.log(f("testing"));
(Note: This is meant to be a clean, canonical dupetarget for the specific issue with arrow functions above.)
When you use the function body version of an arrow function (with {}), there is no implied return. You have to specify it. When you use the concise body (no {}), the result of the body expression is implicitly returned by the function.
So you would write that either with an explicit return:
const f = arg => { return arg.toUpperCase(); };
// Explicit return ^^^^^^
or with a concise body:
const f = arg => arg.toUpperCase();
Examples:
const f1 = arg => { return arg.toUpperCase(); };
console.log(f1("testing"));
const f2 = arg => arg.toUpperCase();
console.log(f2("testing"));
Slightly tangential, but speaking of {}: If you want the concise arrow's body expression to be an object initializer, put it in ():
const f = arg => ({prop: arg.toUpperCase()});
I'm brushing up on knowledge of Javascript and filling in some of the gaps.
for the memoize function, I get why it would console log the function as the memoizeSomeFunction const is just a function expression of someFunction being passed into memoize as an arg. what I can't seem to conceptualize is how the arg being passed into memoizeSomeFunction gets to the return part of the function. can someone elaborate?
const memoize = (fn) => {
console.log(fn);
return (arg) => {
console.log(arg)
}
}
const someFunction = (x = 0, y = 0) => {
return `x is {$x} y is ${y}`;
}
const memoizeSomeFunction = memoize(someFunction);
memoizeSomeFunction(1)
The memoize() function returns a function:
(...args) => {
console.log(...args)
}
That function collects its arguments into an array using the spread (...) syntax, and then un-collects them the same way in the console.log() call.
Thus when you call the function returned from memoize(), it simply logs the arguments passed.
To summarize:
Just one argument is passed to memoize(), your someFunction() function;
The memoize() function returns another function, and that function logs its arguments (and otherwise does nothing with someFunction());
The function source is logged when memoize() is called, and the argument list to the return value from that is logged whenever it is called. If you added another call to that returned function, you'd see those arguments logged separately.
// ES5 equivalent:
const memoize_es5 = function(fn) {
// fn is closured and can be used
// function returned, when it will be called we will have call arguments as well
return function () {
console.log(fn.apply(null, arguments));
}
}
const memoize = fn => (...args) => console.log(fn(...args));
const someFunction = (x = 0, y = 0) => {
return `x is ${x} y is ${y}`;
}
const memoizeSomeFunction = memoize(someFunction); // function received as result of memoize call
memoizeSomeFunction(1, 15); // pass arguments to that function function
// ...args in the arguments is a rest operator
// it just capture all rest arguments into an array:
((first, ...args) => console.log(first, args))(1, 2, 3)
// ...args in a function call is spread operator
// it spreads an array into parameter list:
console.log(...['spread', 'operator'])
I have two files in a folder - index.js and util.js with their code base as follows
Util.js
let obj = {}
obj.sendTransaction = () => {
console.log(arguments);
return new Promise((resolve, reject) => {
// try {
// let data = ethFunction.call()
// resolve(data)
// } catch (e) {
// reject(e)
// }
});
}
module.exports = obj
In Index.js, if I pass arguments to addNewParticipant or its variation then they do not turn up in the arguments object in util.js, for instance
const addNewParticipant = (foo, bar) => {
var ethFunction = myContract.addParticipant.sendTransaction
console.log(ethFunction);
EthUtil.sendTransaction()
}
const addNewParticipantTwo = (foo, bar) => {
var ethFunction = myContract.addParticipant.sendTransaction
console.log(ethFunction);
EthUtil.sendTransaction(ethFunction, foo, bar)
}
and call it such addNewParticpant(1, 2) and , addNewParticpantNew(1, 2) the numbers 1 and 2 do not show up in the arguments object in the util function. In fact, the arguments object remains the same, 4 inputs describing some functions and files in node_modules including Bluebird and a reference to index.js itself
My final aim is to
Pass a function from index.js to util.js
Pass along unknown number of variables
Call the passed function and apply the unknown number of variables to it
Wrap the whole thing in a promise and do some data validation
Ideally arguments[0] would represent a function I would pass and the other would be the values. I would then use
var result = arguments[0].apply(null, Array().slice.call(arguments, 1));
If it helps, the function I want to pass has an optional callback feature
As already mentioned in the comment, fat arrows don't have their own this or arguments objects. The arguments object you're logging is from the function created by the module loader, and its passed arguments.
You can either use a "regular function", or in this case, you can use a ...rest parameter
And, avoid the Deferred antipattern.
//first a little utility that might be handy in different places:
//casts/converts a value to a promise,
//unlike Promise.resolve, passed functions are executed
var promise = function(value){
return typeof value === "function"?
this.then( value ):
Promise.resolve( value );
}.bind( Promise.resolve() );
module.exports = {
sendTransaction(fn, ...args){
return promise(() => fn.apply(null, args));
}
}