Can someone please explain to me this bit of code
return pipe(...fns)(this);
I understand if we didn't have (this), so we returned the reduced functions but (this) confused me.
Full source code here. line 72
https://stackblitz.com/edit/typescript-hv4ntb
It is the same as this:
const pipeFunction = pipe(...fns); // pipe returns a function
const result = pipeFunction(this); // call the returned function with this as argument
return result; // return the result
So if you ever see something like variable(...)(...) you should assume that the variable evaluates to a function that returns a function, like this perhaps:
const variable = (a) => (b) => a + b;
variable(4)(2);
// ==> 6
const partial = variable(8)
[1, 2, 3].map(partial);
// ==> [9, 10, 11]
Javascript is said to have first-class functions (you can read more here on MDN), meaning that you can do with functions what you can do with other types. Storing them into a variable, passing them as argument to other functions, as well as using them as return value from other functions.
The thinking is, just think of functions as values.
In your use-case, a function is just being returned from another function:
function multiply(times) {
return function(number) {
return number * times;
};
}
// as you can see, we are storing the "returned function"
// resulted from calling `multiply` into the `double` variable.
const double = multiply(2);
console.log(
double(5)
);
Now, of course, you could short-circuit the double variable,
and just call the returned function straight away.
function multiply(times) {
return function(number) {
return number * times;
};
}
console.log(
multiply(2)(5)
);
I expect that every time I call the function it will pass 1 as the value of seed parameter and so that value = 1 * 16807 in returned function
so the result of every call will be 16807
I don't understand how this function work
function pseudoRandom(seed) {
let value = seed;
return function() {
value = value * 16807;
return value;
}
}
let generator = pseudoRandom(1);
alert(generator()); // 16807
alert(generator()); // 282475249
alert(generator()); // 1622650073
When you set value = value * 16807, it changes the the variable in generator's closure, so each call to generator sees the value set by the last call.
Here's a simplified version of how closures work:
When you run pseudoRandom(1), you create a closure. Basically, the closure is the combination of the function returned by pseudoRandom and pseudoRandom's local variables. When you call that closure, it updates value in the closure's local variables, so future calls see a different value.
And remember that each time you call pseudoRandom, you create a new closure, with its own local variables, which lets the seeding work correctly.
I recommend reading at least the first 3 or so sections of Mozilla's page on the topic to build a better understanding of how closures work and why they are useful.
This is a scope issue. Change the code to return
return function() {
return value * 16807;
}
or rename the variable in the return function from value to var myValue (for example). In your existing code you are updating value in the outer method. See closures:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#Closure
If you do not assign back to value, every time result will be the same 16807.
function pseudoRandom(seed) {
let value = seed;
return function() {
// value = value * 16807;
return value * 16807;
}
}
Since you are modifying the value after multiplying with 16807, everytime you call generator() it will be 1 * 16807, 1 * 16807 * 16807, 1 * 16807 * 16807 * 16807 and so on.
What's the difference between:
// Example 1 sum(8,2)
console.log(sum(8,2)); // Outputs what??
// Example 2 sum(8)(2)
console.log(sum(8)(2)); // Outputs what??
function sum(x,y) {
return x+y;
}
function sum(x) {
return function(y){
return x+y;
}
}
Why is one used over the other and why?
What you are trying to do is called Function Currying
Try this:
function sum(x) {
return function(y) { return x + y; }
};
var sumWith4 = sum(4);
var finalVal = sumWith4(5);
finalVal = sumWith4(8);
One of the advantages is that it helps in reusing abstract function. For example in the above example I can reuse sumWith4 to add 4 to any number with out calling sum(4,5) explicitly. This was a very simple example. There would be scenarios where in part of the function would be evaluated based on the first param and the other part on the second. So you can create a partial function by providing it with the first param and then reuse the partial function repeatedly for multiple different second params.
I will be assuming that you mean to ask the difference between the invocation of functions which appear like:-
someFunction(x, y)
someFunction(x)(y)
This happens with the use of Closures which happens to be a concept wherein an inner function can carry the environment in which it was created.
var sum = function (x){
return function(y) {
return x+y;
};
};
var addWith5 = sum(5);
/*
This will return a function and not a value
addWith5 = function(y){return 5+y;};
*/
console.log(addWith5(5)); // this will return 11
/*
You can also use add function directly
*/
console.log(sum(5)(6)); // this will return 11
/*
The function returned by sum(5), gets called with the parameter (6)
*/
//Try using this, to make it more clear
function a(x){
return x;
}(5);
// returns 5
EDIT
Removed "closures is a JS concept."
So I'm writing a program in JavaScript in which several of the values within an array are dependent on the outcome of a function. This function is used elsewhere in the code as well, and works fine there.
The code looks something like this:
var Multiplier;
$("#button").on("click", function() { foo(); });
function foo() {
x = document.getElementById("select").value;
setMultiplier(x);
setName(x);
$("#select").hide();
$("#page").show();
}
function setMultiplier(q) {
if (q === "Option 1") {
Multiplier = 1;
return Multiplier;
} else if (q === "Option 2") {
Multiplier = 100;
return Multiplier;
}
}
function mult(base) {
var z;
z = base * Multiplier;
return z;
}
The problem I am having has nothing to do with the setName() as far as I can tell, because that function works fine. Also, Multiplier has the proper value elsewhere. However, when it is used within an array found later in the program, it gives a value of undefined and when I type it into the console it also says Multiplier is not defined. The same thing happens with the mult() function both in the array and in the console, but it works fine elsewhere. Am I missing something here?
EDIT:
So later in the program, mult(base) is called upon in two types of contexts:
1. Within a function (which works) like so:
function blah() {
var s = "<div>$" + mult(75) + "</div>";
s += "<div>$" + mult(150) + "</div>";
document.getElementById("mydiv").innerHTML = s;
}
2. Within an array (which doesn't work) like so:
var array = [["String1", mult(60), 0, [mult(2), mult(5)], mult(30)],
["String2", mult(100), 0, [mult(10), mult(25)], mult(50)]];
You can, and you are.
The issue is that you initialize properties with mult() calls only once, at the time you declare properties. TemplateName is only initialized after someone makes clicky on the UI: before it's initialized its value is null, which doesn't play nice with numbers.
JS won't magically go back and re-initialize properties, or re-run mult every time you access on of its value: when you declare properties and set all those values it's doing it with whatever mult returns at the time properties is declared.
i have a simple function called Range that creates an array of integers based on start, step and end value...
function Range (start, end, step) {
// default step is 1..
if (step === undefined ) step = 1;
// creating an array...
var arr = [], index = 0;
while(start <= end) {
arr[index] = start ;
index += 1;
start += step;
}
// simple function expressions
var getAll = function () {
return arr ;
};
var getOne = function(n) {
return arr[n] ;
};
// returns a unnamed function ..
return function(i) {
if (i === undefined) { return getAll() ;}
else {return getOne(i); }
}; // not an iife
}
so basically Range is a function which returns a unnamed function which again returns a named function expression declared in the function Range.. err.. i dont know.. something like that...
now the below code...
var first10 = Range (1,10) ; // no new ..() here, so no instance should be created.. only Range is called..
var first10Odd = Range(1,20,2) ; // and Range is called again..
alert(first10); // alerts - function(i) { ... }
alert(first10Odd); // alerts- function(i) { ... }
alert(first10()) ; // alerts - 1,2,3,...10
alert(first10Odd()); // alerts - 1,3,5,...19
alert(first10(0)); // alerts - 1
alert(first10Odd(9)); // alerts- 19
why do the alerts alert as specified in the comments??... i think Range is a just a function and not a object constructor and also no instance was created... shouldn't the local variables of function be destroyed as soon as the function is completed??
or is my logic wrong?? what is going on in the above code?? can anyone please explain....
i have made a fiddle of my code here..
sorry for asking this stupid question..
Welcome to the land of closures in Javascript. They can be very powerful and extremely useful once you understand them. But, if your prior experience is with languages that do not have them, they can feel a bit foreign at first.
Some answers/explanation:
Calling Range(x, y) returns a function that can then be called later.
Because that function that is returned is inside another function scope that has variables, a closure is created.
That closure stays alive (even though the outer function has finished executing) because there is a lasting reference to the inner function saved in your variables and that inner function has a reference to the local variables in the outer function. These references keep the closure from being garbage collected (so it stays alive).
That inner function can then reference the variables in the outer function, including the arguments originally passed to it.
This construct allows you to create these custom functions that have arguments pre-built into them.
The notion of this type of closure only exists in some languages. It does not exist in C++, for example.
When the function returned by calling Range(x,y) is itself executed later, it can use any of the variables that were originally in scope to it.
Each call to Range(x,y) causes a new closure to be created.
getAll and getOne are local variables in the outer function that are assigned a function. They access other local variables in the outer function. All of these are in the previously mentioned closure that is created each time Range() is called.
There is lots written about what a closure is (which you can Google and read), but I like to think of it as an execution context that contains everything that was in scope at the time a function is called (including all variables). Each time a function is called, such an execution context it created. Since everything in javascript is garbage collected and will only be freed/destroyed when there are no references left to it, this is true for this execution context too (e.g. closure). As long as something has a reference to it or something in it, then the execution context will stay alive and can be used by any code that might run into that execution context.
Line by line annotation:
// first10 is assigned the anonymous function that the call to Range()
// returned. That anonymous function has access to the original arguments
// passed to the Range(1,10) call and other local variables in that function.
var first10 = Range (1,10) ; // no new ..() here, so no instance should be created.. only Range is called..
// same as the call before, except this also includes the step argument
var first10Odd = Range(1,20,2) ; // and Range is called again..
// this makes sense because Range(1,10) returns a function so
// when you alert it's value, it tells you it's a function
alert(first10); // alerts - function(i) { ... }
alert(first10Odd); // alerts- function(i) { ... }
// When you execute the function in first10, it runs that function
// and the alert shows the return value from that function
// This particular function is set to return the entire array if nothing is passed
// to it
alert(first10()) ; // alerts - 1,2,3,...10
alert(first10Odd()); // alerts - 1,3,5,...19
// This particular function is set to return a specific index from the array
// if an argument is passed to it
alert(first10(0)); // alerts - 1
alert(first10Odd(9)); // alerts- 19
If you know how to use the javascript debugger, you can set a breakpoint on this line if (i === undefined) { return getAll() ;} in the inner function and you will be able to inspect all the variables that are in scope, including start, end and step from the outer function.
You may find this article useful reading as it encapsulates some of the ways that closures can be used with object declarations: http://javascript.crockford.com/private.html (not exactly what is being done here, but might help you understand them).
Welcome to javascript closures. Lets take line by line.
var first10 = Range(1,10);
var first10Odd = Range(1,20,2);
We know that Range is just a function. So, in these two lines we are just calling Range function with 2 and 3 arguments respectively.
Now, what happens when you call a function. The obvious answer is, the body of the function gets executed. What do we have in the body of the function.
if (step === undefined ) step = 1;
var arr = [], index = 0;
while(start <= end) {
arr[index] = start ;
index += 1;
start += step;
}
I hope that the above seen lines are pretty obvious and you don't have any problems with them.
var getAll = function () {
return arr;
};
What does this line do? It creates a function at run time. Why runtime? Lets see an example.
<script>
func1();
var func1 = function() {
alert("Hi");
}
</script>
<script>
func1();
function func1() {
alert("Hi");
}
</script>
If you use the first script block, it will throw error. Why? You are calling a function which hasn't been defined yet. The second case, you are defining the function during javascript parsing time itself. The type of function which was created in the first case is called anonymous function. Let us get back to getAll. Now we know that getAll is simply a variable which points to an anonymous function, lets look at what it does. It returns arr. How does it have access to arr? It is declared outside the function and so it still has access to it. Same case with
var getOne = function(n) {
return arr[n] ;
};
Now the very important part,
return function(i) {
if (i === undefined) {
return getAll();
} else {
return getOne(i);
}
};
What does it do? It returns a function. To be precise, it returns an anonymous function. Whenever Range is called, it creates a new anonymous function, which accepts one parameter and returns it. So, now what do first10 and first10Odd have? Yes. You are right, they have functions. I hope that explains
alert(first10); // alerts - function(i) { ... }
alert(first10Odd); // alerts - function(i) { ... }
Let us examine both the functions. When first10 is called with nothing, I mean, first10(), the parameter i takes the value undefined. So, we are actually making a call to the anonymous function with no parameters and it is supposed to return getAll(). If you remember, first10 was created with Range(1,10);. So, the arr will now have [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].
You might ask, when we return from the function, wont the variables declared inside the function go out of scope. The answer is Yes and No. Yes, when you simply return a value. No, when you return a function. When you return a function, the state of the variables will be maintained. This property is called closures. That is why it returns
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] for alert(first10())
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19] for alert(first10Odd())
1 for alert(first10(0))
19 for alert(first10Odd(9))
Please read more about Closure here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures