Related
How can callback function work with one parameter when it requires 2 (selector and data) to go? Why doesn't it throw an error?
let links = document.querySelectorAll("a");
links.forEach(function(link){
link.addEventListener("click",function(e){
e.preventDefault();
ajax("get",e.target.href,render)
})
})
function ajax(url,metodo,callback){
let xhr = new XMLHttpRequest
xhr.open(metodo,url)
xhr.addEventListener("load",function(){
if(xhr.status==200){
callback(xhr.response)
}
})
xhr.send()
}
function render(selector,data){
document.querySelector(selector).innerHTML = data
}
In javascript, it is not necessary to call with same number of parameters as defined in function definition. If we do not define a default parameter value in function definition, then parameter becomes type of undefined.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters
Default function parameters allow formal parameters to be initialized
with default values if no value or undefined is passed.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
Starting with ECMAScript 2015, there are two new kinds of parameters:
default parameters and rest parameters.
Default parameters: In JavaScript, parameters of functions default to
undefined. However, in some situations it might be useful to set a
different default value. This is where default parameters can help.
In the past, the general strategy for setting defaults was to test
parameter values in the body of the function and assign a value if
they are undefined. If in the following example, no value is provided
for b in the call, its value would be undefined when evaluating a*b
and the call to multiply would have returned NaN. However, this is
caught with the second line in this example:
function multiply(a, b) {
b = typeof b !== 'undefined' ? b : 1;
return a * b;
}
multiply(5); // 5
With default parameters, the check in the function body is no longer necessary. Now, you can simply put 1 as the default
value for b in the function head:
function multiply(a, b = 1) {
return a * b;
}
multiply(5); // 5
For more details, see default parameters in the reference.
Rest parameters: The rest parameter syntax allows us to represent an
indefinite number of arguments as an array. In the example, we use the
rest parameters to collect arguments from the second one to the end.
We then multiply them by the first one.
function multiply(multiplier, ...theArgs) {
return theArgs.map(x => multiplier * x);
}
var arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]
Argument Object:
Using the arguments object, you can call a function with more
arguments than it is formally declared to accept. This is often useful
if you don't know in advance how many arguments will be passed to the
function. You can use arguments.length to determine the number of
arguments actually passed to the function, and then access each
argument using the arguments object.
For example, consider a function that concatenates several strings.
The only formal argument for the function is a string that specifies
the characters that separate the items to concatenate. The function is
defined as follows:
function myConcat(separator) {
var result = ''; // initialize list
var i;
// iterate through arguments
for (i = 1; i < arguments.length; i++) {
result += arguments[i] + separator;
}
return result;
}
You can pass any number of arguments to this function, and it
concatenates each argument into a string "list":
// returns "red, orange, blue, "
myConcat(', ', 'red', 'orange', 'blue');
// returns "elephant; giraffe; lion; cheetah; "
myConcat('; ', 'elephant', 'giraffe', 'lion', 'cheetah');
// returns "sage. basil. oregano. pepper. parsley. "
myConcat('. ', 'sage', 'basil', 'oregano', 'pepper', 'parsley');
To make it throw error, if same number of argument is not passed in function, typescript can be used.
GAME = {};
GAME[1] = {
test: 1,
test2: 2
}
GAMELENGTH = (Math.max.apply(Math.max, Object.keys(GAME))) + 1;
GAMELENGTH2 = (Math.max.apply(Math.apply, Object.keys(GAME))) + 1;
GAMELENGTH3 = (Math.max.apply(null, Object.keys(GAME))) + 1;
console.log(GAMELENGTH);
console.log(GAMELENGTH2);
console.log(GAMELENGTH3);
JSFiddle: http://jsfiddle.net/agx85sba/2/
What exactly am I supposed to use as the first parameter for apply()? As all these different GAMELENGTH's have the same outcome but are taking in different parameters.
fun.apply(thisArg, [argsArray])
thisArg
The value of this provided for the call to fun. Note that this may not be the actual value seen by the method: if the method is a function in non-strict mode code, null and undefined will be replaced with the global object, and primitive values will be boxed.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
For your use-case it does not matter. The actual implementation of Math.max may not care about this.
You use apply to get the maximum of a list of values without the need to write them all to the function call (Math.max(1,2,3,4,5) vs var list = [1,2,3,4,5]; Math.max.apply(null, list)).
I'm looking for a javascript function that can:
Condition (I)
compose another function when it does not have recursion in its definition, kind of like in maths when the function is given a power, but with multiple arguments possible in the first input - e.g. with a (math) function f:
f(x) := x+2
f5(x) = f(f(f(f(f(x))))) = x+10
Condition (II)
Or maybe even input custom arguments into each step of composition:
(52)2)2=
Math.pow(Math.pow(Math.pow(5,2),2),2) = Math.pow.pow([5,2],2,["r",2]])
//first arg set, how times the next, 2nd arg set - "r" stands for recursion -
//that argument will be occupied by the same function
//Using new solution:
_.supercompose(Math.pow,[[5,2],[_,2],[_,2]]) //-> 390625
2((52)3)=
Math.pow(2,Math.pow(Math.pow(5,2),3)) = Math.pow.pow([5,2],["r",2],["r",3],[2,"r"])
//Using new solution:
_.supercompose(Math.pow,[[5,2],[_,2],[_,3]]) //-> 244140625
_.supercompose(Math.pow,[[5,2],[_,2],[_,3],[2,_]]) //-> Infinity (bigger than the max. number)
Note: The above are just templates, the resulting function doesn't have to have the exact arguments, but the more close to this (or creative, for example, a possibility of branching off like this ->[2,4,"r",4,2,"r"], which would also be complicated) the better.
I've been attempting to do at least (I) with Function.prototype, I came up with this:
Object.defineProperty(Function.prototype,"pow",{writable:true});
//Just so the function not enumerable using a for-in loop (my habit)
function forceSlice(context,argsArr)
{returnArray.prototype.slice.apply(context,argsArr)}
Function.prototype.pow = function(power)
{
var args=power<2?forceSlice(arguments,[1]):
[this.pow.apply(this,[power-1].concat(forceSlice(arguments,[1])))];
return this.apply(0,args);
}
//Usage:
function square(a){return a*a;}
square.pow(4,2) //65536
function addThree(a,b){return a+(b||3); }
// gives a+b when b exists and isn't 0, else gives a+3
addThree.pow(3,5,4) //15 (((5+4)+3)+3)
Worst case, I might just go with eval, which I haven't figured out yet too. :/
Edit: Underscore.js, when played around with a bit, can fulfill both conditions.
I came up with this, which is close to done, but I can't get it to work:
_.partialApply = function(func,argList){_.partial.apply(_,[func].concat(argList))}
_.supercompose = function(func,instructions)
{
_.reduce(_.rest(instructions),function(memo,value)
{
return _.partialApply(_.partialApply(func, value),memo)();
},_.first(instructions))
}
//Usage:
_.supercompose(Math.pow,[[3,2],[_,2]]) //should be 81, instead throws "undefined is not a function"
Edit: jluckin's cleareance of terms (recursion-> function composition)
Edit: made example function return number instead of array
The term you are looking for is called function composition, not necessarily recursion. You can apply function composition in javascript easily since you can pass a function as an argument.
I created a small function called compose, which takes a function, an initial value, and the number of times to compose the function.
function compose(myFunction, initialValue, numberOfCompositions) {
if (numberOfCompositions === 1) {
return myFunction(initialValue);
}
else {
return compose(myFunction, myFunction(initialValue), --numberOfCompositions);
}
}
When this function is evaluated, you pass in some function f(x), some initial x0, and the repeat count. For example, numberOfCompositions = 3 gives f(f(f(x)));
If there is one composition, then f(x) is returned. If there are two compositions, compose returns f(x) with f(x) replacing x as the argument, with 1 passed in as the composition so it will evaluate f(f(x)).
This pattern holds for any number of compositions.
Since functions are treated as objects and can be passed as arguments of functions, this method basically wraps your "non-recursive" functions as recursive functions to allow composition.
Success(simplicity wins):
_.supercompose = function (func,instructions,context)
{
var val;
for(var i = 0; i < instructions.length; i++)
{
val = _.partial.apply(_,[func].concat(instructions[i])).apply(context||this,val?[val]:[]);
}
return val;
}
//Usage (with a function constructor for operations):
_.op = function(o){return Function.apply(this,"abcdefghijklmnopqrstuvwxyz".split("").concat(["return " + o]))}
_.op("a+b")(3,5) //-> 8
_.op("a*b")(3,5) //-> 15
_.supercompose(_.op("(a+b)*c*(d||1)"),[[1,2,3],[-5,_,1],[1,2,_,3]])
//-> (1+2)*((-5+((1+2)*3))*1)*3 -> 36
I find the named parameters feature in C# quite useful in some cases.
calculateBMI(70, height: 175);
What can I use if I want this in JavaScript?
What I don’t want is this:
myFunction({ param1: 70, param2: 175 });
function myFunction(params){
// Check if params is an object
// Check if the parameters I need are non-null
// Blah blah
}
That approach I’ve already used. Is there another way?
I’m okay using any library to do this.
ES2015 and later
In ES2015, parameter destructuring can be used to simulate named parameters. It would require the caller to pass an object, but you can avoid all of the checks inside the function if you also use default parameters:
myFunction({ param1 : 70, param2 : 175});
function myFunction({param1, param2}={}){
// ...function body...
}
// Or with defaults,
function myFunc({
name = 'Default user',
age = 'N/A'
}={}) {
// ...function body...
}
ES5
There is a way to come close to what you want, but it is based on the output of Function.prototype.toString [ES5], which is implementation dependent to some degree, so it might not be cross-browser compatible.
The idea is to parse the parameter names from the string representation of the function so that you can associate the properties of an object with the corresponding parameter.
A function call could then look like
func(a, b, {someArg: ..., someOtherArg: ...});
where a and b are positional arguments and the last argument is an object with named arguments.
For example:
var parameterfy = (function() {
var pattern = /function[^(]*\(([^)]*)\)/;
return function(func) {
// fails horribly for parameterless functions ;)
var args = func.toString().match(pattern)[1].split(/,\s*/);
return function() {
var named_params = arguments[arguments.length - 1];
if (typeof named_params === 'object') {
var params = [].slice.call(arguments, 0, -1);
if (params.length < args.length) {
for (var i = params.length, l = args.length; i < l; i++) {
params.push(named_params[args[i]]);
}
return func.apply(this, params);
}
}
return func.apply(null, arguments);
};
};
}());
Which you would use as:
var foo = parameterfy(function(a, b, c) {
console.log('a is ' + a, ' | b is ' + b, ' | c is ' + c);
});
foo(1, 2, 3); // a is 1 | b is 2 | c is 3
foo(1, {b:2, c:3}); // a is 1 | b is 2 | c is 3
foo(1, {c:3}); // a is 1 | b is undefined | c is 3
foo({a: 1, c:3}); // a is 1 | b is undefined | c is 3
DEMO
There are some drawbacks to this approach (you have been warned!):
If the last argument is an object, it is treated as a "named argument objects"
You will always get as many arguments as you defined in the function, but some of them might have the value undefined (that's different from having no value at all). That means you cannot use arguments.length to test how many arguments have been passed.
Instead of having a function creating the wrapper, you could also have a function which accepts a function and various values as arguments, such as
call(func, a, b, {posArg: ... });
or even extend Function.prototype so that you could do:
foo.execute(a, b, {posArg: ...});
No - the object approach is JavaScript's answer to this. There is no problem with this provided your function expects an object rather than separate params.
Lots of people say to just use the "Pass an object" trick so that you have named parameters.
/**
* My Function
*
* #param {Object} arg1 Named arguments
*/
function myFunc(arg1) { }
myFunc({ param1 : 70, param2 : 175});
And that works great, except... when it comes to most IDEs out there, a lot of us developers rely on type / argument hints within our IDE. I personally use PhpStorm (along with other JetBrains IDEs, like PyCharm for Python and AppCode for Objective-C).
And the biggest problem with using the "Pass an object" trick is that when you are calling the function, the IDE gives you a single type hint and that's it... How are we supposed to know what parameters and types should go into the arg1 object?
So... the "Pass an object" trick doesn't work for me... It actually causes more headaches with having to look at each function's docblock before I know what parameters the function expects.... Sure, it's great for when you are maintaining existing code, but it's horrible for writing new code.
Well, this is the technique I use... Now, there may be some issues with it, and some developers may tell me I'm doing it wrong, and I have an open mind when it comes to these things... I am always willing to look at better ways of accomplishing a task... So, if there is an issue with this technique, then comments are welcome.
/**
* My Function
*
* #param {string} arg1 Argument 1
* #param {string} arg2 Argument 2
*/
function myFunc(arg1, arg2) { }
var arg1, arg2;
myFunc(arg1='Param1', arg2='Param2');
This way, I have the best of both worlds. New code is easy to write as my IDE gives me all the proper argument hints. And, while maintaining code later on, I can see at a glance, not only the value passed to the function, but also the name of the argument. The only overhead I see is declaring your argument names as local variables to keep from polluting the global namespace. Sure, it's a bit of extra typing, but it's trivial compared to the time it takes to look up docblocks while writing new code or maintaining existing code.
Update - 2022
JavaScript now has the ability to have something close to named parameters using object destructuring available in ES6. Most newer browsers can use this feature See browser support
This is how it works:
// Define your function like this
function myFunc({arg1, arg2, arg3}) {
// Function body
}
// Call your function like this
myFunc({arg1: "value1", arg2: "value2", arg3: "value3"})
// You can also have default values for arguments
function myFunc2({firstName, lastName, age = 21}) {
// Function body
}
// And you can call it with or without an "age" argument
myFunc({firstName: "John", lastName: "Doe"}) // Age will be 21
myFunc({firstName: "Jane", lastName: "Doe", age: 22})
The best part is that most IDE's now support this syntax and you get good argument hint support
TypeScript
For those of you using TypeScript, you can do the same thing using this syntax
function myFunc(
{firstName, lastName, age = 21}:
{firstName: string, lastName: string, age?: number}
) {
// Function body
}
OR, using an interface
interface Params {
firstName: string
lastName: string
age?: number
}
function myFunc({firstName, lastName, age = 21}: Params) {
// Function body
}
If you want to make it clear what each of the parameters are, rather than just calling
someFunction(70, 115);
do the following:
var width = 70, height = 115;
someFunction(width, height);
Sure, it's an extra line of code, but it wins on readability.
Another way would be to use attributes of a suitable object, e.g. like so:
function plus(a,b) { return a+b; };
Plus = { a: function(x) { return { b: function(y) { return plus(x,y) }}},
b: function(y) { return { a: function(x) { return plus(x,y) }}}};
sum = Plus.a(3).b(5);
Of course for this made up example it is somewhat meaningless. But in cases where the function looks like
do_something(some_connection_handle, some_context_parameter, some_value)
it might be more useful. It also could be combined with "parameterfy" idea to create such an object out of an existing function in a generic way. That is for each parameter it would create a member that can evaluate to a partial evaluated version of the function.
This idea is of course related to Schönfinkeling aka Currying.
Calling function f with named parameters passed as the object
o = {height: 1, width: 5, ...}
is basically calling its composition f(...g(o)) where I am using the spread syntax and g is a "binding" map connecting the object values with their parameter positions.
The binding map is precisely the missing ingredient, that can be represented by the array of its keys:
// map 'height' to the first and 'width' to the second param
binding = ['height', 'width']
// take binding and arg object and return aray of args
withNamed = (bnd, o) => bnd.map(param => o[param])
// call f with named args via binding
f(...withNamed(binding, {hight: 1, width: 5}))
Note the three decoupled ingredients: the function, the object with named arguments and the binding. This decoupling allows for a lot of flexibility to use this construct, where the binding can be arbitrarily customized in function's definition and arbitrarily extended at the function call time.
For instance, you may want to abbreviate height and width as h and w inside your function's definition, to make it shorter and cleaner, while you still want to call it with full names for clarity:
// use short params
f = (h, w) => ...
// modify f to be called with named args
ff = o => f(...withNamed(['height', 'width'], o))
// now call with real more descriptive names
ff({height: 1, width: 5})
This flexibility is also more useful for functional programming, where functions can be arbitrarily transformed with their original param names getting lost.
There is another way. If you're passing an object by reference, that object's properties will appear in the function's local scope. I know this works for Safari (haven't checked other browsers) and I don't know if this feature has a name, but the below example illustrates its use.
Although in practice I don't think that this offers any functional value beyond the technique you're already using, it's a little cleaner semantically. And it still requires passing a object reference or an object literal.
function sum({ a:a, b:b}) {
console.log(a+'+'+b);
if(a==undefined) a=0;
if(b==undefined) b=0;
return (a+b);
}
// will work (returns 9 and 3 respectively)
console.log(sum({a:4,b:5}));
console.log(sum({a:3}));
// will not work (returns 0)
console.log(sum(4,5));
console.log(sum(4));
Coming from Python this bugged me. I wrote a simple wrapper/Proxy for node that will accept both positional and keyword objects.
https://github.com/vinces1979/node-def/blob/master/README.md
NB. My answer of 2016 is not correct and misleading as mentioned in comments.
Trying Node-6.4.0 ( process.versions.v8 = '5.0.71.60') and Node Chakracore-v7.0.0-pre8 and then Chrome-52 (V8=5.2.361.49), I've noticed that named parameters are almost implemented, but that order has still precedence. I can't find what the ECMA standard says.
>function f(a=1, b=2){ console.log(`a=${a} + b=${b} = ${a+b}`) }
> f()
a=1 + b=2 = 3
> f(a=5)
a=5 + b=2 = 7
> f(a=7, b=10)
a=7 + b=10 = 17
But order is required!! Is it the standard behaviour?
> f(b=10)
a=10 + b=2 = 12
This is admittedly pseudocode, but I believe it'll work (I know it works in TypeScript; I'm adopting it for JavaScript).
// Target Function
const myFunc = (a=1,b=2,c=3) => {a+b+c}
// Goal usage:
myFunc(a=5, b=6) // 14
myFunc(c=0) // 3
// Set your defaults
const myFuncDefaults = {a:1, b:2, c:3};
// Override them with passed parameters
const myFuncParams = (params) => { return Object.assign(myFuncDefaults, params)}
// Use the overloaded dict as the input
const myFunc2 = (params) => {
let {a, b, c} = myFuncParams(params);
return myFunc(a, b, c)
}
// Usage:
myFunc({a:5, b:6}) // 14
myFunc({c:0}) // 3
// Written more succinctly:
const myFunc = (params) => {
let {a,b,c} = Object.assign({a:1, b:2, c:3}, params)
return a + b + c
}
For what it's worth, TypeScript makes this kind of nice with hinting:
interface IParams {
a: number;
b: number;
c: number;
}
const myFunc = (params: Partial<IParams>): number => {
const default: IParams = {a:1, b:2, c:3};
let {a, b, c} = Object.assign(default, params)
return a + b + c
}
Yes, well, kind of. I've found two solutions. I'll explain just one.
In this solution, we give up positional arguments, though.
We can use an object (almost identical to a dict in Python) to pass the arguments.
In this example, I'm using the function to generate the name of a image file:
// First we define our function with just ONE argument
function name_of_img(img_desc){
// With this step, any undefined value will be assigned a value
if(img_desc.size == undefined) {img_desc.size = "400x500"}
if(img_desc.format == undefined) {img_desc.format = ".png"}
console.log(img_desc.size + img_desc.format)
}
// Notice inside our function we're passing a dict/object
name_of_img({size: "200x250", format : ".jpg"})
// In Python name_of_img(size="200x250" , format="jpg")
// returns "200x250.jpg"
name_of_img({size: "1200x950"})
// In Python name_of_img(size="1200x950")
// returns "1200x950.png"
We can modify this example, so we can use positional arguments too, we can also modify it so non valid arguments can be passed, I think I will make a GitHub repository about this.
Contrary to what is commonly believed, named parameters can be implemented in standard, old-school JavaScript (for boolean parameters only) by means of a simple, neat coding convention, as shown below.
function f(p1=true, p2=false) {
...
}
f(!!"p1"==false, !!"p2"==true); // call f(p1=false, p2=true)
Caveats:
Ordering of arguments must be preserved - but the pattern is still useful, since it makes it obvious which actual argument is meant for which formal parameter without having to grep for the function signature or use an IDE.
This only works for booleans. However, I'm sure a similar pattern could be developed for other types using JavaScript's unique type coercion semantics.
I need a method that can have an arbitrary number of parameters. In C# we have the params statement. Do we have anything similar in JavaScript?
There is the arguments collection, which contains all arguments passed to the function.
There is a) no need to specify "optional" arguments in the function signature and b) any function accepts any number of parameters.
function foo() {
console.log(arguments);
}
foo(1,2,3,4); // logs [1, 2, 3, 4]
Likewise, there is no need to supply "required" arguments in a function call:
function foo(a, b, c, d) {
console.log(arguments);
}
foo(1,2); // logs [1, 2]
Any argument named in the signature but not supplied in the function call will be undefined.
Note that arguments behaves like an Array, but technically it isn't one. For example, you can call arguments[0], but you can't call arguments.slice(). What you can do to get around this is using the Array prototype:
Array.prototype.slice.call(arguments, 1, 2);
The so-called rest parameter ... is a new (ES6+) addition to the language and makes working with variadic functions more comfortable. #ArunCM's answer explains it.
I know this thread is too old but I believe something is missing here.
There is Rest parameter (introduced in ECMAScript 6) which will allow us to represent an indefinite number of arguments as an array.
It always returns an array. Which means even in defensive JavaScript land, it’s ok to do things like check .length of rest without guards.
Syntax :
function(a, b, ...theArgs) {
// ...
}
There are three main differences between rest parameters and the arguments object:
rest parameters are only the ones that haven't been given a separate name, while the arguments object contains all arguments passed to the function
the arguments object is not a real array, while rest parameters are Array instances, meaning methods like sort, map, forEach or pop can be applied on it directly;
the arguments object has additional functionality specific to itself (like the callee property).
Additional reading : Spread
function f(x, ...y) {
// y is an Array
return x * y.length;
}
console.log("Expected result : 3*2 = 6 & Actual result : " + f(3, "hello", true));
console.log("Expected result : 3*4 = 12 & Actual result : " + f(3, "a", true, "b", 1));
//here we are not passing anything to "y" but its still safe to check .length of "y" because it always return an array.
console.log("Expected result : 3*0 = 0 & Actual result : " + f(3));
Yes. arguments.
function concatStrings () {
var str = '';
for (var i = 0; i < arguments.length; i++) {
str += arguments[i];
}
return str;
}
Be aware that arguments isn't an array, so it doesn't have methods like join or push. It's just an array-like object (with numerical properties and a length property) so it can be iterated through.
JavaScript has arguments object inside functions. It contains of all params passed to the function.
More info
It is some sort of implicit in the special variable "arguments". Use like this:
function something(arg1, arg2) {
for (var i = 0; i < arguments.length; i++) {
var x = arguments[i];
}
}
Then you can call it like something(1, 2, 3, 'a', 'b', 'c')
More examples here: http://www.jtricks.com/javascript_tutorials/varargs.html
Javascript functions can accept any number of parameters by default. You can see them with the arguments variable.
See here.