First of all, the way the function is being called throws me off. How can a function be called with two separate parens like the one in this example?
addTogether(4)(3)
Lastly, could someone please explain how the closure works in this if statement(please see full code below)?
if(a) {
return function(y) {
if(checkIfNum(y)) {
return a + y;
} else {
return undefined;
}
};
If we call addTogether() like this:
addTogether(4)(3), I understand that argument a is set to 4 but not sure how y is set to 3.
function addTogether() {
function checkIfNum(num) {
return typeof num === 'number' ? num : undefined;
}
var a = checkIfNum(arguments[0]);
var b = checkIfNum(arguments[1]);//if there is no second argument, var b = undefined;
if(arguments.length > 1) {
return a && b ? a + b : undefined;
} else {
if(a) {
return function(y) {
if(checkIfNum(y)) {
return a + y;
} else {
return undefined;
}
};
} else {
return undefined;
}
}
}
console.log(addTogether(4)(3));//7
On the first invocation, addTogether(4), 'var a = checkIfNum(arguments[0]);' resolves to 'var a = 4'. The first invocation of addTogether() causes our anonymous function (y) to be invoked and returned to the main function addTogether(). When anonymous function (y) is invoked, JavaScript searches for the value of 'y'. How does JavaScript decide that '3' will be the value of 'y'? My guess is that on the first invocation of addTogether() or addTogether(4), the argument object associated with addTogether() is set to the value of 4. Once 4 gets passed to the function addTogether(), we now have 'a' = 4 trapped in the closure created by addTogether() and at the same time, essentially we have three things happening : #1 : 'a' = 4, # 2 : the argument of addTogether() is now set to the value of 3 or addTogether(3), #3 : anonymous function (y) is returned and invoked causing JavaScript to search for the value of 'y'. JavaScript sees that at this exact point in time, the argument of addTogether() is set to the value of 3 so JavaScript sets the value of 'y' to 3. How does JavaScript know to set 'y' to the value of 3? When a function is invoked inside another function, does JavaScript automatically set the value of the argument of the, for lack of better words, "child" function to the value of the argument of the "parent" function? Is there something about the arguments object that I'm missing here?
Great question. I remember scratching my head over this same example about two years ago.
For your first question, "How can a function be called with two separate parens like the one in this example?":
This is only possible because addTogether returns another function. You then pass that function another integer 3. It then adds them up to give you 7.
Then you ask about closures: a closure is formed when you add additional scope inside a scope giving the inner scope access to values in the outer scope. In this case a closure is formed when you declare a function within a function.
For your second question: "I understand that argument a is set to 4 but how y is set to 3":
Here's the logic of the function addTogether:
1) Check if one or two arguments are supplied.
2) If two arguments are supplied return the addition of the numbers iff they are both numbers.
3) If there is just one, return an anonymous function which takes an integer and adds its input to a variable a available to the anonymous function because of it being enclosed inside an outer function which declares a.
This is where the closure is formed. This anonymous function, since it is inside the scope of the outer function addTogether has access to all of the outer function's properties including a and the method checkIfNum.
In your actual case:
1) You supply one argument 3 so addTogether returns an anonymous function.
2) You call this anonymous function with a value of 3. This ends up running the logic in the anonymous function, first checking if 3 is a number, then adding 3 to 4, return 7.
I love JavaScript.
Related
This is not a debugging question or a how-to question. This is a conceptual question.
I was finding it hard to wrap my head around what this "second scope" thing is, but overlooking the details I came up with this explanation:
If a function is stored (in some way) like this:
{
// function body written using undefined parameters.
// When the function is called the arguments are assigned to the parameters.
}
Declaring default parameters does this:
{ // Second scope
parameter1 = "something"
parameter2 = 5
{
// function body written using the above parameters.
// When the function is called the arguments or default values get assigned to the parameters.
}
}
Is this what really happens under the hood? If not, then what happens in there? The ECMAScript docs are way above my level. Maybe someone could provide the explanation in layman's terms? Thanks!
That's a pretty good explanation! Yes, the parameter list has its own scope. Let me expand on your explanation a bit and then explain why the additional scope there.
When you call a function without default parameter values, a new scope is created for the body of the function, and the parameters are created in that scope like top-level variables in the function. So, conceptually:
<<
let param1 = /*...the argument value provided for param 1 if any */;
let param2 = /*...the argument value provided for param 2 if any */;
// Start of function code
var variable1;
let variable2;
// End of function code
>>
(I'm using <</>> delimiters instead of {/} because the scopes aren't just block scopes, they isolate var as well; so I picked an arbitrary delimiter.)
When there are default parameter values, as you've described, there's an additional scope involved:
<<
let param1 = /*...the argument value provided for param 1 if any */;
let param2 = /*...the argument value provided for param 2 if any */;
<<
// Start of function code
var variable1;
let variable2;
// End of function code
>>
>>
The reason is that default parameter values are expressions, not just literals. For example:
function example(a = 1, b = a + 1) {
// ^^^^^−−−−−−−−−−−−− expression, not just literal
return a + b;
}
console.log(example()); // 1 + (1 + 1) = 3
console.log(example(2)); // 2 + (2 + 1) = 5
One reason that matters is that if there were just one scope for the parameter list and the function body, that would mean an expression in the parameter list could refer to hoisted variables and functions declared in the function body. The hoisted variables would just have the value undefined, so that wouldn't have been useful, but the hoisted functions would be initialized with their function bodies, leading to a situation like this:
// Doesn't work because of the additional scope
function example(a, b = blarg()) {
function blarg() {
return 42;
}
// ...
}
That causes a ReferenceError because the function body's scope isn't available in the parameter list's scope.
IIRC there were arguments for and against and a fair bit of discussion, but in the end the decision was to put the parameter list in its own scope to prevent that and other oddities.
I am a little confused regarding closures in this example
function f(param){
var n=function(){ //n is assigned the function that returns param
return param;
};
param++; //increments 1 and n keeps a reference to the param
return n;
}
var inner=f(1);
inner();
I understand the concept of closures, I just dont understand how it works in this example.
Lets see in steps whats happening here:
you call function f with argument 1 and assign the result to variable inner.
When f(1) is called, the scope of f has 2 variables (param and n)
The variable params is the passed argument and n is a function.
So, inside function f -
variable n is initialized to a function, then param is incremented, then n is returned from the function f.
This returned function (n) is assigned to inner.
when inner is called, it returns param - which is in scope of function n due to closure.
Hope the steps were clear.
Now, you're doubt was how n got access to param++. It didn't, param++ was already executed when f(1) was called. All n has is just a reference to the value of param.
In param becomes a local variable to the function which is not same as the argument of the function f. The function f is returning n which is a function
function f(param) {
var n = function() { //n is assigned the function that returns param
return param;
};
param++; // here param become a local variable of the function f
return n;
}
var inner = f(1);
console.log(inner());
Here in this example, the local variable param ends up within a closure of that anonymous function. Here in this case, until the outer function returns, it can change the local execution context which will be used by the anonymous function whenever it gets executed.
I'm new-ish to Javascript and need to make a change to this one script. I noticed this line of code that thoroughly confused me, however.
function FIValidateForm(aForWhom, aDoNotShowWarning, aFromWhere)
{
try
{
PAIWarnings = '';
var pBlFalg = true;
if (pBlFalg)
pBlFalg = mfpCheckForFISave(aForWhom, aDoNotShowWarning, aFromWhere);
if (pBlFalg == true)
pBlFalg = PAIErrors();
if ((pBlFalg) && (FIValidateForm.arguments.length == 1))
mfpIFWarnings();
return pBlFalg;
}
catch (err)
{
logError(err, arguments.callee.trace());
}
}
During run time, if I put a breakpoint on that third if statement and inspect FIValidateForm.arguments I can see an array with 3 items. The first contains a string, the second is null, and the third is undefined. The array still has a length of 3.
Am I correct in assuming that no matter what one were to pass to this method, FIValidateForm.arguments.length == 1 will always be false? Or is there some other value I'm unaware of / alternative way to call this method so that arguments.length would equal 1?
Edit: I see JS has an arguments.length and a Function.length. The latter returns the expected number of parameters... So then how does one call a method so that the value would be 1 when the function is defined with 3?
Am I correct in assuming that no matter what one were to pass to this method, FIValidateForm.arguments.length == 1 will always be false?
No, you can make its FIValidateForm.arguments.length 1 by doing this:
FIValidateForm(justOneArgHere);
arguments represents the actual arguments to the function. (See 1 below about arguments vs. FIValidateForm.arguments.)
If you want the function's arity (the number of formal declared arguments), that's the FIValidateForm.length and it doesn't vary.
So then how does one call a method so that the value would be 1 when the function is defined with 3?
JavaScript doesn't enforce the number of formal arguments at all; you can call your function with no arguments, one argument, or 15. If a formal argument (a declared one, like your aDoNotShowWarning) is not supplied, the value it will have within the function call will be undefined. If you supply more arguments than are declared, they are only accessible (in ES5 and below) via the arguments pseudo-array. (In ES2015 and above, you can make your last argument a "rest argument", which means it will be an array of all arguments from that point on.)
Example:
function foo(a, b, c) {
console.log(arguments.length);
console.log(foo.length);
}
foo(1);
foo(1, 2);
1 The arguments property of the function (e.g., FIValidateForm.arguments) is a non-standard extension to JavaScript, which is expressly deprecated by strict mode (the example above would throw an error in strict mode). Just use the freestanding symbol arguments, which is defined for normal functions (as though it were a local variable).
(And in ES2015 or higher, you can avoid using arguments at all by using rest notation on your argument declarations instead.)
No, it won't always be false.
If you call it as FIValidateForm(), then FIValidateForm.arguments.length === 0
If you call it as FIValidateForm(arg1), then FIValidateForm.arguments.length === 1
If you call it as FIValidateForm(arg1, arg2), then FIValidateForm.arguments.length === 2
If you call it as FIValidateForm(arg1, arg2, arg3), then FIValidateForm.arguments.length === 3
And so on
Howver, do not use FIValidateForm.arguments. It's bad practice and forbidden in strict mode. Use arguments instead.
TL;DR: If you ever call the function with only one argument, functionName.arguments.length === 1 will be true.
Yes, FIValidateForm.arguments.length gives you exactly the number of arguments you call FIValidateForm with.
Consider this function f:
function f(first, second) {
console.log('first argument:', first);
console.log('second argument:', second);
console.log('number of arguments:', f.arguments.length);
}
and these two cases:
// case 1:
f('something');
// prints:
// first: something
// second: undefined
// number of arguments: 1
// case 2:
f('something', undefined);
// prints:
// first: something
// second: undefined
// number of arguments: 2
Notice how undefined is the "default" value for missing arguments, but unlike an explicit undefined argument, a missing argument is not counted in f.arguments.length.
Hope somebody finds the time to explain little about functions in functions and scoping.
I am trying to understand little more on functions and scope of variables and found a quite good tutorial, but this part I just do not get.
The task:
Create a function sum that will work like that: sum(a)(b) = a+b and accepts any number of brackets. Examples:
sum(1)(2) == 3
sum(5)(-1)(2) == 6
The solution:
function sum(a) {
var sum = a;
function f(b){
sum += b;
return f;
}
f.toString = function() { return sum };
return f; //line 12
}
alert( sum(1)(2) ); // 3e
The Explanation:
To make sum(1) callable as sum(1)(2), it must return a function.
The function can be either called or converted to a number with valueOf.
The solution is really self-explanatory:
My interpretation:
This f in function f(b) returned to the scope, which is from line 02 - 12.
The f in f.toString, is the currently returned f from function(b)
The next return f returns to the scope which is outside the function sum(a).
Problem:
I cannot figure out, where I need to think differently, because like I described above, the function would not be called again, so where is the part of the code, that make the 'several parentheses' possible?
Moreover, did I correctly assume where the fs are returned? Would be great if somebody would give some explanations.
The function sum returns a function, which we refer to as f.
The function f also returns a function: in fact, the function f returns itself.
When the function f is defined inside of sum, it gets permanent access to all variables currently visible in the scope chain. Here, it includes the locally-defined variable sum (the local running sum tally) and f (the function itself). (A "closure" is what we call the functional code of f along with all its in-scope variables.)
Because f returns itself, you can chain f with repeated calls:
var this_is_f = sum(1);
var same_f_again = this_is_f(2);
var f_a_third_time = same_f_again(3);
Or simply:
sum(1)(2)(3);
It is important to note that in my first example, I don't create new functions; instead, I just refer to the exact same function object with three different identifiers.
Each call to sum creates a brand-new f with a new local sum in its scope (here, I mean the local sum defined on the first line of the function named sum). However, calling the function sum does not clobber any old f, because each call to sum instantiates a new f (and knows nothing about any other fs that have been created on prior calls to sum). That way, you can have multiple tallies running:
var first_tally = sum(1)(2); // first: 3
var second tally = sum(4)(5); // second: 9
first_tally(3); // first: 6
second_tally(6); // second: 15
The reason you're able to see a meaningful result at any time is that f stingifies to the value of sum, instead of showing you its source code.
If you take this code and simplify it to the bare minimum I would be easier to understand. Take a function add that sums only 2 numbers:
function add(x,y) {
return x + y;
}
The above is a "normal" function. If you don't pass all the arguments you'll get unexpected results.
Now, if you want a function that adds 2 to any number, you could partially apply an argument to add, for example:
function add2(x) {
return add(2, x);
}
But in JavaScript we have first class functions (objects that can be passed around), so a function can take functions as inputs and return other functions. This is where "currying" comes in handy. While "partial application" lets you fix function arguments, "currying" takes a function of many arguments and breaks it down into a function of a single argument that returns another function of one single argument until all the arguments have been evaluated, in order, and then returns the result. For example:
function add(x) {
return function(y) {
return x + y;
}
}
Now you can create a function add2 by currying the function add:
var add2 = add(2);
add2(1); //=> 3
The normal function and the curried one have equivalent computations where:
add(1, 2) === add(1)(2)
This is what makes "several parentheses" possible.
In JavaScript "scope" and "closure" refer to functions but they're different concepts. A "scope" determines the reach/privacy of your variables while a "closure" lets you encapsulate code and carry it around. In the curried function above the variable x is kept in memory through closure because it's referenced inside the returned function object.
A particular limitation of "currying" is that you can't have functions of dynamic arity; the number of arguments must be fixed. This is not the case in the code you post where your sum function must be able to add a new number to the previous sum indefinitely.
Similarly to "currying" there's the idea of "generators"; a pattern to model sequences of lazy computation, in this case just adding a number to the previous sum on demand.
function sum(a) { // begin closure
var sum = a; // kept in memory...
function f(b) {
sum += b; //...because you use it here
return f;
}
f.toString = function() { return sum };
return f;
} // end closure
A different (maybe more clear) way to express your code would be to return an object to chain the computations, where you can either add a new number to the previous sum, or get the total sum so far:
function add(a) {
var sum = a;
return {
plus: function(b) {
sum += b;
return this;
},
sum: function() {
return sum;
}
}
}
add(1).plus(2).plus(3).sum(); //=> 6
In your code the returned function f acts as plus and toString as sum which retrieves the value.
Line 01-13 defines the function sum within the global scope.
Line 15 calls sum and changes scope to inside the function.
The variables a and sum and the closure function f are all defined in the function's scope - with the sum variable hiding the function definition from the global scope.
I'll skip over the toString bit here as its not important till later (when it gets very important).
The function sum finally returns a reference to the closure function f to the global scope as an anonymous function (since f can only be referenced by name from within its containing function's scope).
Back to line 15 - sum(1)(2) is the same as (sum(1))(2) and since sum(1) returns f then this can be reduced to (f)(2) or, more simply, f(2).
Calling f(2) adds 2 to sum - sum is defined in two scopes: as a function in the global scope; and as a variable (currently assigned the value of 1) within that function which hides the definition from the global scope - so, in f, the sum variable is set to 1+2=3.
Finally, in f, the function returns itself.
Back, again, to line 15 - f(2) returns f (although the named function f cannot be referenced in the global scope and, again , is treated as an anonymous function)
alert() is processed and the anonymous function (referred to as f) is converted to a string to be alerted; normally when alert() is called on a function it will display the source for the function (try commenting out Line 10 to see this). However, since f has a toString method (Line 10) then this is invoked and the value of sum (as defined in the function containing f) is returned and 3 is alerted.
Let's step through the function line by line:
function sum(a) {
This part is pretty self-explanatory; we have a function named sum which accepts an argument a.
var sum = a
Here we have a local variable called sum that is set to the value of the argument that is passed in.
function f(b) {
sum += b
return f
}
This is an inner function called f that accepts an argument called b. This b is then added to the value of sum from the outer scope (i.e., inside the scope of the function that is also called sum). After that, the function returns itself.
f.toString = function() { return sum }
This is the fun part! When you normally console.log a function, it will just spit out the function's source. Here we are redefining the toString method to instead be a function that spits out the value of sum. This is why you end up seeing the running total that is displayed instead of the function's source even though what you are returning is still a function.
Finally we have:
return f
So you basically have a function sum, returning a function that returns itself. The function sum basically sets everything up, but after calling sum(3), you then work with f, which you repeatedly call.
So the first time you call sum, you essentially get back this function:
function f(b) {
sum += b; //value of sum is 3
return f;
}
In this context, the value of sum will be the value of a that you passed into the initial call of the function sum. However, since the toString of f has been redefined, you only see the value 3. Then let's say you do sum(3)(4).
You get back, as before:
function f(b) {
sum += b; //value of sum is 3
return f;
}
But then you are actually calling f with an argument of 4 (basically f(4)). Since f is an inner function, it has full access to the scope of its parent function. This parent function (sum) is maintaining the the running total in a variable called sum, which is accessible to f. So when you now call f(4), you have b set to 4 and sum having a value of 3:
function f(b) { //b is 4
sum += b; //value of sum is 3 + 4, which is 7
return f;
}
So with each subsequent pair parentheses you are making repeated calls to the same f which is maintaining a running tally.
Another way is to think of sum as a kind of factory that can give you different f's, all of which keep their own running tallies (basically behaving like accumulators):
var firstSum = sum(4);
var secondSum = sum(2);
firstSum(5); //equivalent to sum(4)(5) returns 9
secondSum(2); //equivalent to sum(2)(2) returns 4
There are 3 concepts being played here
closures (no scope).
functions are first class OBJECTS in javascript (allows for chaining f(a)(b)(c)). There's no need to save a handle to the function to call it later.
I'll give you a run-down and then add some extra explanations afterwards
function sum(a) {
// when sum is called, sumHolder is created
var sumHolder = a;
// the function f is created and holds sumHolder (a closure on the parent environment)
function f(b) {
// do the addition
sumHolder += b;
// return a FUNCTION
return f;
}
// change the functions default toString method (another closure)
f.toString = function() {return sumHolder;}
// return a FUNCTION
return f
}
/*
* ok let's explain this piece by piece
*
* you call sum with a parameter
* - parameter is saved into sumHolder
* - a function is returned
*
* you call the returned function f with another parameter
* EXPLANATION: { sum(a) } returns f, so let's call f as this => {...}()
* - this private (priviledged) function adds whatever it's been passed
* - returns itself for re-execution, like a chain
*
* when it all ends {{{{}(a)}(b)}(c)} the remainder is a FUNCTION OBJECT
* this remainder is special in that it's toString() method has been changed
* so we can attempt to cast (juggle) it to string for (loose) comparison
*
*/
The concept behind closures is quite easy to understand but it's application make's your head spin until you get used to the idea that there is no function scope in javascript, there is closures and these are powerfull critters indeed
// this anonymous function has access to the global environment and window object
(function()
{// start this context
var manyVars, anotherFunc;
function someFunc() {
// has access to manyVars and anotherFunc
// creates its own context
};
anotherFunc = function () {
// has access to the same ENVIRONMENT
// creates its own context
};
}// whatever is in these keys is context that is not destroyed and
// will exist within other functions declared inside
// those functions have closure on their parent's environment
// and each one generates a new context
)();
Functions are first class objects. What does this mean? I'm not sure myself but let me explain with some further examples:
// how about calling an anonymous function just as its created
// *cant do the next line due to a language constraint
// function(){}()
// how about a set of parens, this way the word "function" is not the first expression
(function(){}());
// the function was created, called and forgotten
// but the closure inside MAY STILL EXIST
function whatDoIReturn() {
return function (){alert('this is legal');return 'somevalue';}();// and executed
}// returns 'somevalue'
Don't take this word for word. Go look for other people's code, check the Crockford and ask any and all questions that come up
What is the relationship between a function and a value? I thought that a function was a type of value; however, functions both contain values (arguments) and return values too.
I'm (obviously) new to programming, and want to ensure that I have a solid conceptual foundation as I move my way through JavaScript.
Functions do things. Variables hold values (data).
A function can accept data as arguments. A function can also return data, but does not have to. Consider this function which just adds two numbers together:
function addNumbers(numberA, numberB) {
var total = numberA + numberB;
console.log(total);
}
This is a function which accepts two arguments. Within the function's code block, those arguments' values are assigned to the variables numberA and numberB. The function's code creates another variable, total, and assigns the value of numberA added to the value of numberB. The function then calls another function, console.log, with the value of total passed in as an argument.
Now, the function can also return values. Let's modify this function a bit:
function addNumbers(numberA, numberB) {
var total = numberA + numberB;
return total;
}
If you were to call this function now, you get back the value of total. If I were to run this:
console.log(addNumbers(5, 5));
You would see 10 in the console. My number literal values were passed as arguments to addNumbers. The function did its work and returned to me the value of its total variable. This value is now passed in as an argument to console.log.
If that isn't crystal clear yet, then please read other tutorials online before continuing.
Now, in JavaScript functions are just like anything else. You can assign them to variables as well!
var newAddNumbers = addNumbers;
console.log(newAddNumbers(5, 5)); // Also returns 10 in the console
When you type:
function someFunction () {
This is no different than:
var someFunction = function () {
The function itself is assigned to the variable someFunction. In our original example, the function itself was assigned to addNumbers. So yes, function is a type just like number, object, boolean, etc.
If I have a function:
function add(a, b) {
return a + b;
}
add is a function. All functions are values; I can place them in a variable or pass them as an argument, for example.
a and b are arguments of add, but the function has not been called, so they do not have values. Similarly, the function has been called, so it has no return value.
When I call the function:
add(1, 2);
The function executes with a and b initially set to 1 and 2 respectively for that invocation.
If I call it again with different arguments:
add(3, 4);
Then this time a and b are initially set to 3 and 4; however, these a and b not only have different values than the last time; they really are different variables. Every time you call a function, the arguments are essentially variables, which are local not only to that function but to that invocation of that function.