Javascript - Passing static value to a callback function - javascript

I want to create callback function with some parameters, but I want that one of the values within never change and be set when the function is created!
P.e.
let a = 2;
let y = (b) => { let staticValue = a; return staticValue * b; }
y(1) => 2 -> OK
then
a = 3
y(1) => 3 -> Not OK -> I want the function to have the original value of a.
I know, this happens because the variable a is only evaluated when the function is called. But is there any workaround?

You can accomplish this with what is called an IIFE (immediately invoked function expression)
let a = 2;
const y = (staticValue => b => staticValue * b)(a);
a = 44;
console.log(y(1));
What's happening here is that you have two functions. The first one, staticValue => ... is immediately invoked, and staticValue is given the value of a. Since a is given as an argument of the IIFE, once the function is invoked staticValue won't change, even if the value of a is changed.
The return value of the first function is a second function, b=> ....

let a = 2
let makeY = () => {
let staticValue = a;
return (b)=> staticValue * b;
}
let y = makeY();
or
let a = 2
let y = ((staticValue, b) => {
return staticValue * b;
}).bind(null, a)

you can use closure
function first (a) {
function second (b) {
return a * b;
}
return second;
}
let x = first(2) // the inner function second will close around the variable a which is 2 in this case
console.log(x(3))
let y = first(5) // the inner function second will close around the variable a which is 5 in this case
console.log(y(3))

I think you could apply a Functional programming approach.
const getYFn = (a , b) => {
return a * b;
}
const a = 2
const y = getYFn.bind(null, a);
// the constant y now is a function that partially applied first param
console.log(y(1)); // 2
console.log(y(3)); // 6

Related

Please explain to me. How does this Javascript code work step by step if that possible

n the function below, a comparison is made (finding out) which function called it. if the one is the most nested (internal), then a number is returned, and if the most external, then the function is executed.
var n = function(digit) {
return function(op) {
return op ? op(digit) : digit;
}
};
these are variables to which function calls are assigned.
var zero = n(0);
var one = n(1);
var two = n(2);
var three = n(3);
var four = n(4);
var five = n(5);
var six = n(6);
var seven = n(7);
var eight = n(8);
var nine = n(9);
and this is the "operator" function
function plus(r) { return function(l) { return l + r; }; }
function minus(r) { return function(l) { return l - r; }; }
function times(r) { return function(l) { return l * r; }; }
function dividedBy(r) { return function(l) { return l / r; }; }
and this is the performance of functions, for the sake of which everything was written
one(plus(two())), 3);
seven(times(five())), 35);
four(plus(nine())), 13);
eight(minus(three())), 5);
that is, I understand how the code works in general, but I don’t understand the details, and I’m not able to consciously write such code myself because I don’t understand how it works in detail. This is where the problem is.
thanks in advance
The functions returned by n and plus, etc., are closures over the paramter value n, etc., were called with. For instance, with n:
var n = function(digit) {
return function(op) {
return op ? op(digit) : digit;
}
};
// ...
var one = n(1);
var two = n(2);
So in the case of two, the function n returned (assigned to two) closes over the value of digit for the call (2), so it has access to it later.
Code calling two can do one of two things:
Call it with no arguments: two()
Call it with a function: two(plus(one()))
If two is called with no arguments, op will be undefined, so this:
return op ? op(digit) : digit;
becomes effectively
return digit;
So that means, two() returns 2.
But if you pass a function into two, it calls that function with 2 as an argument. That's where things like plus come into it:
function plus(r) { return function(l) { return l + r; }; }
plus returns a function that closes over r. That function, when you call it with a value (l), returns the result of l + r.
So let's look at that in action: two(plus(one())). Evaluation is inside out, so:
one() is called with no arguments, so it returns 1; now we effectively have:
two(plus(1))
plus() is called with 1 and returns function(l) { return l + r; } which is effectively function(l) { return l + 1; } (because r is 1); so now we effectively have:
two(function(l) { return l + 1; })
two is called with the function from Step 2 as op. Since it was given a function, two calls op(2) and returns its result.
op (the function from Step 2) returns 2 + 1
The result is 3.
Here's a version that makes it easier to see what's going on:
const n = function(digit) {
console.log(`n: creating "digitFn" for ${digit}`);
const digitFn = function(op) {
if (op) {
console.log(`digitFn: evaling op(${digit})`);
const result = op(digit);
console.log(`digitFn: returning ${result}`);
return result;
}
console.log(`digitFn: no "op", returning ${digit}`);
return digit;
};
return digitFn;
};
const plus = function(r) {
console.log(`plus: creating "opFn" for + ${r}`);
const opFn = function(l) {
console.log(`opFn: evaling ${l} + ${r}`);
const result = l + r;
console.log(`opFn: returning ${result}`);
return result;
};
return opFn;
};
console.log("main: Creating `one` and `two`");
const one = n(1);
const two = n(2);
console.log("main: Doing `two(plus(one()))`");
console.log(two(plus(one())));
.as-console-wrapper {
max-height: 100% !important;
}
This overall thing is called partial application: Taking a function that takes N arguments, "baking in" one or more of those arguments to produce a function that takes < N arguments (because some are already provided).
Side note: Because you'll see this in the wild, I'll just note that you'll probably see these written as concise-form arrow functions, which are written like this: (params) => expression (if there's only one parameter, the () are optional: param => expression). What makes those concise-form arrow functions is the fact that the first thing after the arrow (=>) is not a { (more here). When called, a concise arrow function evaluates the expression and returns the result (implicitly, there's no return keyword in a concise arrow function). Those can seem complicated and intimidating at first, until you get used to reading them. Here's n:
// Does exactly what your original `n` does
const n = digit => op => op ? op(digit) : digit;
That breaks down like this:
digit => ____ is n, which returns the result of the expression ____
op => ____ is the function n returns
op ? op(digit) : digit is the expression the function created by n evaluates
Here's the full list:
const n = digit => op => op ? op(digit) : digit;
const zero = n(0);
const one = n(1);
const two = n(2);
const three = n(3);
const four = n(4);
const five = n(5);
const six = n(6);
const seven = n(7);
const eight = n(8);
const nine = n(9);
// Do exactly the same thing your original functions do
const plus = r => l => l + r;
const minus = r => l => l - r;
const times = r => l => l * r;
const dividedBy = r => l => l / r;

JavaScript: Accept Division Function as Argument Into Another Function That Returns New Function --> Returns Quotient

I have a function that divides two input arguments:
const divide = (x, y) => {
return x / y;
};
I have a second function that takes the divide function as its input argument and returns a new function.
function test(func) {
return function(){
return func();
}
}
const retFunction = test(divide);
retFunction(24, 3)
I am expecting the returned value to be 8 (24 / 3). But I'm getting a returned output of 'NaN'. What am I doing wrong?
You need to pass the possible arguments to the function: ...args:
const divide = (x, y) => {
return x / y;
};
function test(func) {
return function(...args) {
return func(...args);
}
}
const retFunction = test(divide);
const result = retFunction(24, 3);
console.log(result);

JavaScript: create function that accepts callback as input and returns function; Output depends on invoke count

The objective of my code is:
Write a function "once" that accepts a callback as input and returns a function. When the returned function is called the first time, it should call the callback and return that output. If it is called any additional times, instead of calling the callback again it will simply return the output value from the first time it was called.
I tried the code below:
const once = (inputFunc) => {
let invCount = 0;
let firstCallOutput;
return function (num) {
invCount ++;
if (invCount === 1){
firstCallOuput = inputFunc(num);
return inputFunc(num);
}
else {
return firstCallOuput;
}
}
}
const addByTwoOnce = once(function(num) {
return num + 2;
});
// UNCOMMENT THESE TO TEST YOUR WORK!
console.log(addByTwoOnce(5)); //should log 7
console.log(addByTwoOnce(10)); //should log 7
console.log(addByTwoOnce(9001)); //should log 7
My code console logs out the correct values (7) in all three situations. But it fails 2/3 test specs.
What am I doing wrong? How can I pass the two test specs?
Here's a simplified once function -
const once = (f, memo) => x =>
memo === undefined
? (memo = f(x), memo)
: memo
const addTwo = x =>
x + 2
const addTwoOnce =
once(addTwo)
console.log(addTwoOnce(5)) //should log 7
console.log(addTwoOnce(10)) //should log 7
console.log(addTwoOnce(9001)) //should log 7
If you want to safeguard the call site from being able to set the memo, you can make the memo a local variable instead of a parameter -
const once = f =>
{ let memo
return x =>
memo === undefined
? (memo = f(x), memo)
: memo
}
Or maybe you want to safeguard against the potential for the user-supplied function to return undefined. These are all choices you can make with minimal impact on the semantic structure of the code -
const once = f =>
{ let hasRun = false
let memo
return x =>
hasRun
? memo
: (hasRun = true, memo = f(x), memo)
}
Related: constant will return a constant value, regardless of its input -
const constant = x => _ =>
x
const always7 =
constant(7)
console.log(always7(5)) //should log 7
console.log(always7(10)) //should log 7
console.log(always7(9001)) //should log 7
Related: memoise will cache a value for each unique input, only recomputing f if the input has not been seen before -
const memoise = (f, memo = new Map) => x =>
memo.has(x)
? memo.get(x)
: (memo.set(x, f(x)), memo.get(x))
let fib = n =>
n < 2
? n
: fib (n - 1) + fib (n - 2)
console.time("original")
console.log(fib(40))
console.timeEnd("original")
// 1503.43 ms
fib = memoise(fib)
console.time("memoised")
console.log(fib(40))
console.timeEnd("memoised")
// 0.175 ms
Ok,
First we will create a once function that accepts a callback function.
Then we need to create a variable to check if this is the first time or not.
You can make a boolean variable or counter whatever you want. OK,
Then we make a variable result to grap the output of the callback with the initial value of 0
function once(func) {
let isOnce = true
let result = 0
}
OK, after that, let's create a function that will return the callback value if this is the first time, and if not, we will just return the output value from the first time, which we stored to the result
function once(func) {
let isOnce = true
let result = 0
function runOnce(num) {
if(isOnce) {
isOnce = false
result = func(num)
return result
} else {
return result
}
}
}
Finally, we will return the runOnce function.
function once(func) {
let isOnce = true
let result = 0
function runOnce(num) {
if(isOnce) {
isOnce = false
result = func(num)
return result
} else {
return result
}
}
return runOnce
}
Ok, now we need to create a callback function that takes the input and increments it by 2.
function addByTwo(input) {
return input + 2
}
So, time to check
const always7 = once(addByTwo);
console.log(always7(5))
console.log(always7(10))
console.log(always7(9001))
It always runs once and gets the same result every time.
the result is always be 7, click

addOne takes in a number as a parameter // and returns that numbers +1?

Function addOne returns undefined result...
const t = 5;
const b = 8;
function addOne () {
add (t + b);
return addOne;}
Pls help to get a sum of 5 + 8 with this function.
const t = 5;
const b = 8;
function addOne () {
return t+b;
}
console.log(addOne()); //13
I am not sure what you are asking, since your method's name is not matching with your implementation. But here are some code that might help you:
const t = 5;
const s = 8; // Note that I have renamed the parameter's name
function addOne () {
return s + 1;
}
function addOneToParameter(x) {
return x + 1;
}
function addTwoConstants () {
return t + s;
}
function addTwoParameters (a, b) {
return a + b;
}
console.log(addOne()); // 9 (The constant 's' + 1)
console.log(addTwoConstants()); // 13 (The constant 's' + constant 't')
console.log(addTwoParameters(1,2)); // 3 (The first parameter + the second parameter)
console.log(addOneToParameter(4)); // 5 (The parameter + 1)
In your original question, you don't need to use a function to perform an addition of two integers. In other words, simply use '+' as operand. Furthermore, pay attention how to return a value from your function.

JavaScript Default Parameters: passing no values

let add = (a = 0,b = 0) => {
return a+b;
};
console.log(add(5,2));
What I expected was: 0
and the result is: 7
If I pass a = 5 and b = 2 then in the function add, a and b are already assigned 0, so it should return 0. Why 7?
let add = (a = 0,b = 0) => {
return a+b;
};
SO your function will be evaluated something like this
let add = (a, b) => {
a = (typeof(a) !== undefined) ? a : 0;
b = (typeof(b) !== undefined) ? b : 0;
return a + b; //your function code start from here.
}
So if you pass add(5, 2), condition (typeof(a) !== undefined) will be true and 5 will be assign to a and same for b, but if you pass add(5) then condtion for a become ttrue and a is assign as 5 but condition for b is false so b will be assign as 0.
Default parameters are overwritten if provided by the call. Otherwise they would be useless, as you could never change them.
That is the whole point of default values: if you do not provide values when calling the function, the defaults are used, otherwise the values passed in the function call are used.
let add = (a = 2, b = 1) => {
return a + b;
};
console.log(add(5, 2)); // no default will be used
console.log(add(5)); // only second default will be used
console.log(add(undefined, 4)); // only first default will be used
In any language, the default value is only used when there is no other value assigned.
So, whenever you assigned any value to the variable it changes the value.
Same is going with your concept
let add = (a = 0,b = 0) => {
return a+b;
};
console.log(add(5,2)); // it will return 7
console.log(add()); // it will return 0

Categories

Resources