I understand the case when a function may have less arguments than the function signature allows, such as:
function sum(x, y=1) { return x+y; }
console.log(sum(5));
Or more parameters if its a vargs/rest function:
function sum(...rest) {
let s = 0;
for (let n of rest) s += n;
return s;
}
console.log(sum(1,2,3,4,5));
But why does the following not raise an error?
'use strict';
function addEmUp() {
let sum = 0;
for (let arg of arguments) sum += arg;
return sum;
}
console.log(addEmUp(1,2,3,4,5));
The default values for parameters and the rest parameters are a relatively new functionality of JavaScript, they were introduced in ES2015. Before that, the only way to have a function with any number of arguments was by using the arguments object. It has been available since the first versions of JavaScript.
No matter how a function accesses its actual parameters, it can be called with less or more parameters than its declaration requires. When there are less actual values than declared parameters on the call, the remaining parameters are not initialized (their value is undefined), when the function is called with more values than it is declared, the extra values can be accessed only by using the arguments object (or with the rest syntax).
Related
I am learning javascript and have seen anonymous functions written like this without any explanation:
const sum = (function() {
return function sum(x,y,z){
return (x+y+z);
};
})();
console.log(sum(1,2,3)); //6
The way I read it is: declare a function anonymously and assign it to the const sum. Call sum() with the parameters and console.log() the results.
This is very confusing to me as I don't understand why it is written the way it is. Some questions are:
How is sum accepting parameters when the outermost function has no parameters specified?
Why are we not specifying the parameters on the outermost function?? Why is it returning itself and which 'sum' gets called when?
Apologies if it is too dumb or obvious. I have struggled a lot and have finally decided to ask here.
First of all this function is not only anonymous. it's an iife (immediately invoking function) and it's returning sum function. So const variable sum is actually sum function that is returned by iife function.
console.log(sum(1,2,3));
So, in the above line sum is referring to the function sum returned by iife function not the iife function itself
For more understanding about iife check - https://developer.mozilla.org/en-US/docs/Glossary/IIFE
For better understanding, we can expand it to:
const _sum2 = function() { // anonymous function
return function sum(x,y,z){
return (x+y+z);
};
}
const sum = _sum2(); // value of _sum2 returns
// it is the same as
const sum = function sum(x,y,z){
return (x+y+z);
}
console.log(sum(1,2,3));
Test it yourself:
const sum = (function() {
return function sum(x,y,z){
return (x+y+z);
};
})();
console.log('const sum = ' + sum.toString());
such syntax is used to protect intermediate valiables and functions. In your case there are no such variables, but:
const sum = (function() {
const n = 10;
function protected() {
return n;
}
return function sum(x,y,z){
return protected() * (x+y+z);
};
})();
console.log(sum(1,2,3)); // evaluates to 60
function protected and variable n are sealed and not exposed to your global environment.
For beginners, the following code is horribly loaded with confusing unnecessary misinformation:
const sum = (function() {
return function sum(x,y,z){
return (x+y+z);
};
})();
The outer anonymous function is NOT necessary since there is no inner variables or functions to protect -- so why use it at all?? It only serves to confuse!!
Why use "sum" to name the inner returned anonymous function? It has nothing to do with the const sum, and only causes more confusion here!!
All the above code is completely unnecessary, redundant, and confusing when considering the following is the same:
const sum = (x, y, z) => x + y + z;
console.log(sum(1,2,3));
Reading about functional programming - got to currying, example has a simple currying function. I understand everything except the last else block.
var curry = function (fn, fnLength) {
fnLength = fnLength || fn.length;
return function () {
var suppliedArgs = Array.prototype.slice.call(arguments);
if (suppliedArgs.length >= fn.length) {
return fn.apply(this, suppliedArgs);
} else if (!suppliedArgs.length) {
return fn;
} else {
return curry(fn.bind.apply(fn, [this].concat(suppliedArgs)), fnLength - suppliedArgs.length);
}
};
};
If the supplied args are >=, call the function with the supplied arguments.
Else if suppliedArgs.length is falsy, return the original function without doing anything.
Else ???
I think recursively call the function?
I don't understand what .bind.apply accomplishes.
Is [this] just in an array because suppliedArgs.push wouldn't return the array?
Start by looking at how you call Function#bind():
fun.bind(thisArg[, arg1[, arg2[, ...]]])
Then consider how you use Function#apply():
fun.apply(thisArg, [argsArray])
So given for bind() we need to call it on a function, and give it multiple parameters (not an array), and all we have is an array of arguments (suppliedArgs in the code), then how can we do that? Well, the main way you can call a function that takes multiple arguments instead of a single argument that is an array is to use .apply() on the function. So then we have fn.bind.apply(...something...).
The first parameter to .apply() is the this value - which needs to be the function to be bound in the case of .bind() (see below for an explanation of why). Hence fn.bind.apply(fn, ...).
Then, the second parameter to .apply() is an array of all the arguments to the function you are invoking, which in the case of .bind() is thisArg[, arg1[, arg2[, ...]]]. Hence we need a single array, with the first value being the value for this within the function, followed by the other arguments. Which is what [this].concat(suppliedArgs) produces.
So the whole fn.apply.bind(fn, [this].concat(suppliedArgs)) thing produces a correctly bound function that will have the supplied arguments to the current function "prefilled", with the correct this context. This function that is produced is then passed as the fn parameter in a recursive call to curry(), which in turn will produce another function in the same way as the top level call will.
The overall effect is that whenever you call a function created by curry(), if you don't pass the expected number of parameters, you will get a new function which takes the remaining number of parameters, or you will evaluate the original function with the entire list of parameters passed in correctly.
e.g.
function addAllNums(a, b, c, d, e) {
return a + b + c + d + e;
}
var curriedAddAll = curry(addAllNums, 5);
var f1 = curriedAddAll(1); // produces a function expecting 4 arguments
var f2 = f1(2, 3); // f2 is a function that expects 2 arguments
var f3 = f2(4); // f3 is a function that expects 1 argument
var f4 = f3(5); // f4 doesn't expect any arguments
var ans = f4(); // ans = 1 + 2 + 3 + 4 + 5 = 15.
// OR var ans = f3(5); => same result
Why the different thisArg values?
Probably the most confusing thing about this line of code is the two different values for thisArg in .bind() and .apply().
For .apply(), the thisArg is what you want the value of this to be inside the function you are calling .apply() on. e.g. myFunction.apply(myObj, ['param1', 'param2']) is equivalent to myObj.myFunction('param1', 'param2').
In this particular case, .bind() is executed on the fn function, so we want fn to be the this value for .bind(), so it knows what function it is creating a bound version of.
For .bind(), the thisArg is what the value of this will be inside the bound function that is returned.
In our case, we want to return a bound function that has the same this value as we currently have. In other words, we want to maintain the this value correctly within the new function, so it doesn't get lost as you create new functions which happens when you call a curried function with less arguments than it expects.
If we did not maintain the this value correctly, the following example wouldn't log the correct value of this. But by maintaining it, the correct value will be output.
var myObj = {
a: 1,
b: curry(function (a, b, c, d) {
console.log('this = ', this);
return a + b + c + d;
})
};
var c = myObj.b(1,1,1); // c is a function expecting 1 argument
c(1); // returns 4, and correctly logs "this = Object {a: 1, b: function}"
// if "this" wasn't maintained, it would log the value of "this" as
// the global window object.
The last else block is the main and most important part of the curry function, as it is the actual line that carries the logic for currying.
return curry(fn.bind.apply(fn, [this].concat(suppliedArgs)), fnLength - suppliedArgs.length);
This is what returns the new function that needs n-1 arguments from your previous function. Why? It's a combination of multiple things:
fn.bind.apply simply calls a function in the context of the function itself, while supplying the needed args (suppliedArgs). Note how the next parameter to curry is fnLength - suppliedArgs.length, which reduces the arguments needed to what was passed.
Let's explain it with the help of ES6. Things are going to become more obvious.
// Imagine we have the following code written in ES5
function fn(a, b, c) {
console.log(a, b, c);
}
var arr = [1, 2, 3];
var funcWithBoundArguments = fn.bind.apply(fn, [null].concat(arr));
Let's convert ES5 to ES6 code
// ES6
function fn(a, b, c) { console.log(a, b, c) }
let arr = [1,2,3];
let funcWithBoundArguments = fn.bind(null, ...arr)
You see? When you bind a function we have to explicitly enumerate all the arguments like:
fn.bind(null, 1, 2, 3)
But how could we bind the content of an array if we don't know its content in advance?
Right, we have to use .bind.apply() where:
the 1st argument of apply is the function (fn) we bind
the 2nd argument is an array which gets the context (as the first item of array) that we bind our function to and the rest of the items of the array are the arguments (which number is variable) we bind to our function (fn).
I just started reading Functional JavaScript and immediately was introduced to a function that I don't understand:
function splat(fun) {
return function(array) {
return fun.apply(null, array);
};
}
var addArrayElements = splat(function(x, y) { return x + y });
addArrayElements([1, 2]);
//=> 3
How does splat(function(x, y) { return x + y }) work. It's called with the array [1,2], but it seems like the anonymous function inside the call to splat takes two parameters, not one array.
Putting console.log(fun) on line 2 of this code shows that fun is the entirety of the anonymous function(x, y) { return x + y }. console.log(array) after return function(array) { shows that array is [1, 2]. Where does array come from then?
Thanks much.
It might be simpler to see how this function would have been written without using the .apply method:
function splat(fun) {
return function(array) {
return fun(array[0], array[1]);
};
}
First you call splat, passing it a function:
var add = function(x,y){ return x + 1 };
var ff = splat(add);
At this point, ff refers to the function(array) function, meaning its an one-argument function. The private variable fun refers to the add function.
Now, you call ff passing its one argument
ff([1,2]);
and it uses the values in the array to call fun with two arguments
return fun(array[0], array[1]);
The only difference between this and the real example is that the apply method lets you work with any argument array length instead of hardcoding a specific length (2) like I did.
//Every time we call this function, we get another one back
function splat(fun) {
return function(array) { // <-- this one will be returned in splat();
return fun.apply(null, array);
};
}
//Step one, call splat, pass a function as parameter
var addArrayElements = splat(function(x, y) { return x + y });
/*
Get back a function that accepts an array, and will execute the function we just passed in on it
*/
// This will call the newly created function, func will be available because it's in a closure
addArrayElements([1, 2]);
The last thing is that, even if the anonymous function takes two parameters, we call apply on it so it will bind array[0] ==> x and array[1] ==> y
This is an example of a higher order function. That's a function that takes functions as arguments and returns functions instead of just regular values (though functions are "just regular values" in Javascript). In this case:
function splat(fun) {
splat takes a function as its argument...
return function(array) {
...and returns a new function which takes an array...
return fun.apply(null, array);
...and when called calls the first fun function with the array .applied as its arguments.
So splat takes one function which expects several parameters and wraps it in a function which takes an array of parameters instead. The name "splat" comes from languages like Ruby, where a * (a "splat" or "squashed bug") in the parameter list of a function accumulates an arbitrary number of arguments into an array.
var addArrayElements = splat(function(x, y) { return x + y });
addArrayElements is now basically:
function (array) {
// closed over variable:
// var fun = function(x, y) { return x + y }
return fun.apply(null, array);
}
Here this is realized by a closure, which closes over and "preserves" the original fun passed to splat in the new returned function.
addArrayElements = function(array) { fun.apply(null, array); };
BUT
it has a closure whereby the variable context of its containing scope (that of the splat function that created the anonymous function) remains visible and accessible.
In JavaScript, functions are first-class objects that can be referenced and passed as arguments or, as in this case, through the closure mechanism.
Edit: about JavaScript and scope
In most languages, variables are, by default, local to the scope they're defined in (which usually is a function's local symbol table). By contrast, in JavaScript a variable is local only if it is defined using the var keyword; otherwise, the symbol will be looked back in the chain of the containing scopes, up to the implicit root object (which in the case of web browsers is window. I.e.,
function foo() { someVar = "bar"; }
foo();
alert(someVar); // shows "bar"
Not being restricted to the local scope, the symbol has been (purposely or not) leaked to the root scope.
Taking it one step further:
function foo() {
var baz = function() {
someVar = "bar";
};
baz();
}
foo();
alert(someVar); // shows "bar"
However, if you declare someVar within foo:
function foo() {
var someVar;
var baz = function() {
someVar = "bar";
};
baz();
alert("someVar in foo=" + someVar); // shows "bar"
}
foo();
alert("someVar in root=" + window.someVar); // shows "undefined"
Note that in this last version I needed to use window.someVar instead of just someVar because someVar never got defined as a variable in the root scope nor as a property of the root object, which caused an error.
a more functional approach uses bind(), which is short enough you don't really need splat anymore, and it's always nice to eliminate closures:
var addArrayElements = Function.apply.bind( function(x, y) { return x + y } , null );
addArrayElements([1, 2]); // === 3
This question already has answers here:
Passing arguments forward to another javascript function
(5 answers)
Closed 5 years ago.
I think I need something like ruby's splat * here.
function foo() {
var result = '';
for (var i = 0; i < arguments.length; i++) {
result += arguments[i];
}
return result;
}
function bar() {
return foo(arguments) // this line doesn't work as I expect
}
bar(1, 2, 3);
I want this to return "123", but instead I get "[object Arguments]". Which makes sense, I suppose. It's passing the object that represents the arguments, but not the arguments individually.
So how do I simply forward any number of arguments to another function that takes any number of arguments?
UPDATE: Since ES6, you can use the spread syntax to call a function, applying the elements of an iterable object as argument values of the function call:
function bar() {
return foo(...arguments);
}
Note that you can also receive a variable number of arguments as a real array, instead of using the arguments object.
For example:
function sum(...args) { // args is an array
return args.reduce((total, num) => total + num)
}
function bar(...args) {
return sum(...args) // this just forwards the call spreading the argument values
}
console.log(bar(1, 2, 3)); // 6
In the days of ES3/ES5, to correctly pass the arguments to another function, you needed to use apply:
function bar() {
return foo.apply(null, arguments);
}
The apply method takes two parameters, the first is the thisObj, the value of it will be used as the this value inside the invoked function, if you use null or undefined, the this value inside the function will refer to the global object, in non-strict mode, otherwise is undefined.
The second argument that apply expects is an array-like object that contains the argument values to be applied to the function.
Check the above example here.
Try this return foo.apply(this,arguments). Also you can just use Array.prototype.slice.apply(arguments).join('') for your foo function.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
JavaScript: var functionName = function() {} vs function functionName() {}
What's the difference between:
function sum(x, y) {
return x+y;
}
// and
var sum = function (x, y) {
return x+y;
}
Why is one used over the other?
The first is known as a named function where the second is known as an anonymous function.
The key practical difference is in when you can use the sum function. For example:-
var z = sum(2, 3);
function sum(x, y) {
return x+y;
}
z is assigned 5 whereas this:-
var z = sum(2, 3);
var sum = function(x, y) {
return x+y;
}
Will fail since at the time the first line has executed the variable sum has not yet been assigned the function.
Named functions are parsed and assigned to their names before execution begins which is why a named function can be utilized in code that precedes its definition.
Variables assigned a function by code can clearly only be used as function once execution has proceeded past the assignment.
The first tends to be used for a few reasons:
The name "sum" shows up in the
stacktrace which makes debugging
easier in many browsers.
The name
"sum" can be used inside the
function body which makes it easier
to use for recursive functions.
function declarations are "hoisted"
in javascript, so in the first case,
the function is guaranteed to be
defined exactly once.
Semicolon insertion causes
var f = function (x) { return 4; }
(f)
to assign 4 to f.
There are a few caveats to keep in mind though.
Do not do
var sum = function sum(x, y) { ... };
on IE 6 since it will result in two function objects being created. Especially confusing if you do
var sum = function mySym(x, y) { ... };
According to the standard,
function sum(x, y) { ... }
cannot appear inside an if block or a loop body, so different interpreters will treat
if (0) {
function foo() { return 1; }
} else {
function foo() { return 2; }
}
return foo();
differently.
In this case, you should do
var foo;
if (0) {
foo = function () { return 1; }
} ...
The first one is a named function statement, the second one assigns an anonymous function expression to a variable.
The function statement is added to its scope immediately - you don't need to run it before being able to call it, so this works:
var y = sum(1, 2);
function sum(x, y) {
return x + y;
}
But the function expression is only assigned to the variable when the code is executed, so this doesn't work:
// Error here because the function hasn't been assigned to sum yet.
var y = sum(1, 2);
var sum = function(x, y) {
return x + y;
}
An advantage of the expression form is that you can use it to assign different functions to the expression at different points - so you can change the function, or use a different one under different conditions (such as depending on the browser being used).
An advantage of a named function statement, is that debuggers will be able to display the name. Although, you can name function expressions:
var sum = function sum(x, y) {
return x + y;
}
But this can be confusing since the two names are actually in different scopes and refer to different things.
The two code snippets you've posted there will, for almost all purposes, behave the same way.
However, the difference in behaviour is that with the second variant, that function can only be called after that point in the code.
With the first variant, the function is available to code that runs above where the function is declared.
This is because with the second variant, the function is assigned to the variable foo at run time. In the first, the function is assigned to that identifier foo at parse time.
More technical info
Javascript has three ways of defining functions.
Your first example is a function declaration. This uses the "function" statement to create a function. The function is made available at parse time and can be called anywhere in that scope. You can still store it in a variable or object property later.
Your second snippet shows a function expression. This involves using the "function" operator to create a function - the result of that operator can be stored in any variable or object property. The function expression is powerful that way. The function expression is often called an "anonymous function" because it does not have to have a name,
The third way of defining a function is the "Function()" constructor, which is not shown in your original post. It's not recommended to use this as it works the same way as eval(), which has its problems.
The difference is...
This is a nameless function
var sum = function (x, y) {
return x+y;
}
So if you alert(sum); you get "function (x, y) { return x + y; }" (nameless)
While this is a named function:
function sum(x, y) {
return x+y;
}
If you alert(sum); now you get "function sum(x, y) { return x + y; }" (name is sum)
Having named functions help if you are using a profiler because the profiler can tell you function sum's execution time...etcetera instead of an unknown functions's execution time...etcetera
here's an other example:
function sayHello(name) { alert('hello' + name) }
now,suppose you want modify onclick event of a button, such as it says "hello world"
you can not write:
yourBtn.onclik = sayHello('world'), because you must provide a function reference.
then you can use second form:
yourBtn.onclick = function() { sayHello('workld'); }
Ps: sorry for my bad english!
They mean the exact same thing. It's just syntactic sugar. The latter is IMO more revealing of what JavaScript is really doing; i.e. "sum" is just a variable, initialised with a function object, which can then be replaced by something else:
$ js
js> function sum(x,y) { return x+y; }
js> sum(1,2);
3
js> sum=3
3
js> sum(1,2);
typein:4: TypeError: sum is not a function
js> sum
3