Recently I have seen these functions in tutorials. Are they equivalent?
(_ => console.log(1))();
(() => console.log(1))();
The two functions do exactly the same thing. The only difference is that the top function takes one parameter, _, while the other takes zero. This doesn't matter in this example, since you don't use the _ variable.
If however, you are using _ as a variable name, and you use it in the function, you will run into problems. Example:
(_ => console.log(_))();
is not the same thing as
(() => console.log(_))();
In the first line, the function prints the value of the parameter _, which, in this case is undefined, since no value is passed to it. In the second line, the function prints the value of the global variable _. This can become a problem if you use a library like underscore.js, where the variable _ is used.
A "fat arrow" (=>) function can be declared with a single identifier parameter name, or with a parenthesized lists of zero or more parameters. Your first example
(_ => console.log(1))();
is the first case, with the parameter name being "_". The second example is a parameter list with no parameters:
(() => console.log(1))();
Neither function makes use of its parameters, and both invocations pass no parameters. That is, both function calls have no actual arguments; the statements both end with (). Whether the two are "equivalent" or not depends on your definition of "equivalent". In both cases, exactly the same thing will happen. However, the anonymous fat-arrow functions are not exactly the same.
No, they are not equivalent. The first is an anonymous fat arrow function with 1 parameter, the second is an anonymous fat arrow function with 0 parameters. The first, thus, relies on the fact that passing too few arguments to a function is not an error in ECMAScript.
The underscore _ is sometimes used to indicate a parameter that is required to fulfill a certain contract but is actually ignored. However, in this case, that is a misuse of this convention since the parameter isn't required: the function is called without arguments, so there is no need to declare a parameter.
Related
What is the reason of putting ( ) in the end for Immediately Invoked Function Expression in javascript
(function() {
// Code that runs in your function
})( /* this parenthesis in the end */ )
An Immediately Invoked Function Expression is a:
(function() { ... }) ← Function Expression which is Immediately Invoked → ()
To elaborate, (function() { ... }) is merely defining the function, and a function which is defined but never called is doing absolutely nothing.
In order for the code in the function to be executed, it needs to be invoked (often referred to as calling the function). That is why you wrap the function definition in parentheses (making it an expression that evaluates to a reference to the function) and then immediately invoke (or call) the function with any arguments () - or no arguments as in your sample.
It is more or less equivalent to doing this:
const someFunc = (function() { ... }); //merely assigns a function, the code inside doesn't run
someFunc(); //invokes the function (but in this case it isn't immediate)
except in this case you've bound the function reference to a variable and so it is no longer an IIFE.
The reason is purely syntactical. The JavaScript parser has to be able
to easily differentiate between function declarations and function
expressions. If we leave out the parentheses around the function
expression, and put our immediate call as a separate statement
function(){}(3), the JavaScript parser will start processing it, and will conclude, because it’s a separate statement starting with the
key- word function, that it’s dealing with a function declaration.
Because every function declaration has to have a name (and here we
didn’t specify one), an error will be thrown. To avoid this, we place
the function expression within parentheses, signaling to the
JavaScript parser that it’s dealing with an expression, and not a
statement. There’s also an alternative way of achieving the same goal:
(function(){}(3))
By wrapping the immediate function definition and call within
parentheses, you can also notify the JavaScript parser that it’s
dealing with an expression.
Those four expressions are variations of the same theme of
immediately invoked function expressions often found in various
JavaScript libraries:
+function(){}();
-function(){}();
!function(){}();
~function(){}();
This time, instead of using parentheses around the function
expressions to differentiate them from function declarations, we can
use unary operators: + , - , ! , and ~ . We do this to signal to the
JavaScript engine that it’s dealing with expressions and not
statements.
Reference: johnresig.com/
I’d like to know both for regular all-in-the-family JS developer-defined functions, as well as predefined DOM methods: what happens if I try to call IE’s attachEvent with the signature of the WHATWG’s addEventListener? For instance:
elem.attachEvent('onbillgates\'mom', function(e){ this.mount(); }, false);
Specifically, note the third argument false. Will that trip anything up, even though the attachEvent method’s signature only calls for two arguments?
What about this example?
function foo(FirstOf2, SecondOf2) {
console.log(FirstOf2 + SecondOf2);
}
foo(1, 2, true);
JavaScript doesn't have the concept of a fixed parameter list. For your own functions you can always specify as many parameters as you want and pass in as many as you want which ever type you want.
For built-in functions, which correlate to native code, it depends.
You asked on what it depends:
Let's look at the ECMA-262
Section 15 about built-in (not to confuse with host) functions in general
Unless otherwise specified in the description of a particular function, if a function or constructor described in this clause is given fewer arguments than the function is specified to require, the function or constructor shall behave exactly as if it had been given sufficient additional arguments, each such argument being the undefined value.
Alright. If I pass in less arguments than needed, it depends on the spec of the function itself (scroll down section 15 to find the spec for each built-in function).
Unless otherwise specified in the description of a particular function, if a function or constructor described in this clause is given more arguments than the function is specified to allow, the extra arguments are evaluated by the call and then ignored by the function. However, an implementation may define implementation specific behaviour relating to such arguments as long as the behaviour is not the throwing of a TypeError exception that is predicated simply on the presence of an extra argument.
Passing in too many arguments should never raise a TypeError. But still it may raise other errors. Again, it depends on the function you talk about.
You were talking explicitly about the DOM and not about built-in functions. To be honest I can't find the corresponding parts of the spec. The ECMA spec is so much easier to read then the w3 website.
Won't hurt. You can even call a function with less parameters than it takes, as long as the function code is ok with a few undefined values.
I came across this important, however old, question; and I hope it'll be beneficial for future generations to share my experiments with it:
One can use the arguments object in order to access a function's arguments, regardless of the amount of arguments in the function's signature.
It's worth mentioning that this doesn't apply to arrow functions:
function singleArg(x) {
console.log(arguments);
}
singleArg(1, 2); // Called with 2 arguments
singleArg(); // Called with 0 arguments
// Results in an error, as 'arguments' isn't defined for arrow functions
((arg) => console.log(arguments))(1);
It's stated in the documentation that arguments isn't exactly an Array:
“Array-like” means that arguments has a length property and properties indexed from zero, but it doesn't have Array's built-in methods like forEach() and map().
Hence the following code results in an error:
(function singleArg(x) {
console.log(arguments); // This line works
arguments.forEach(x => console.log(x)); // This causes an error
})(1, 2);
Upon calling a function with less arguments than in its signature, they're assigned undefined:
(function twoArgs(a, b) {
console.log(`a: ${a}\nb: ${b}`);
})(1);
Try taking a look at this post and perhaps this one.
From MDN:
The arguments object is a local variable available within all
functions; arguments as a property of Function can no longer be used.
You can refer to a function's arguments within the function by using
the arguments object. This object contains an entry for each argument
passed to the function, the first entry's index starting at 0.
You can use the arguments object if you call a function with more
arguments than it is formally declared to accept. This technique is
useful for functions that can be passed a variable number of
arguments.
function myConcat(separator) {
var result = "";
// iterate through non-separator arguments
for (var i = 1; i < arguments.length; i++) {
result += arguments[i] + separator;
}
return result;
}
I don't think it will mess anything up unless you are explicitly dealing with the implicit arguments array. Why are you doing this though?
What is the difference between these functions:
callback(x: string[], y: string[]){
console.log(x.concat(y).join(', '));
}
and
(c,d) => console.log(c.concat(d).join(', '))
?
From theoretical view first is a standard function, the second is so called arrow function.
From the Documentation, arrow functions differs from standard functions in this criterias
An arrow function expression has a shorter syntax than a function
expression and does not have its own this, arguments, super, or
new.target. These function expressions are best suited for non-method
functions, and they cannot be used as constructors.
Arrow functions does not have their own this, they get it from the
upper scope, where are defined.
They don't have arguments object inside the body, which has every
standard function and via that you can access passed in arguments.
You can create an object via arrow function - see point 1.
From Typescript view, same as above and also that you haven't provide argument types for the arrow function. Also be aware that you mistyped argument name in the arrow function.
The first is TypeScript and performs type checking on the inputs.
The second is JavaScript and throws an error because the variable names in the arguments don't match the variable names used in the function. (That error aside, it does the same thing, just without the type checking).
I’d like to know both for regular all-in-the-family JS developer-defined functions, as well as predefined DOM methods: what happens if I try to call IE’s attachEvent with the signature of the WHATWG’s addEventListener? For instance:
elem.attachEvent('onbillgates\'mom', function(e){ this.mount(); }, false);
Specifically, note the third argument false. Will that trip anything up, even though the attachEvent method’s signature only calls for two arguments?
What about this example?
function foo(FirstOf2, SecondOf2) {
console.log(FirstOf2 + SecondOf2);
}
foo(1, 2, true);
JavaScript doesn't have the concept of a fixed parameter list. For your own functions you can always specify as many parameters as you want and pass in as many as you want which ever type you want.
For built-in functions, which correlate to native code, it depends.
You asked on what it depends:
Let's look at the ECMA-262
Section 15 about built-in (not to confuse with host) functions in general
Unless otherwise specified in the description of a particular function, if a function or constructor described in this clause is given fewer arguments than the function is specified to require, the function or constructor shall behave exactly as if it had been given sufficient additional arguments, each such argument being the undefined value.
Alright. If I pass in less arguments than needed, it depends on the spec of the function itself (scroll down section 15 to find the spec for each built-in function).
Unless otherwise specified in the description of a particular function, if a function or constructor described in this clause is given more arguments than the function is specified to allow, the extra arguments are evaluated by the call and then ignored by the function. However, an implementation may define implementation specific behaviour relating to such arguments as long as the behaviour is not the throwing of a TypeError exception that is predicated simply on the presence of an extra argument.
Passing in too many arguments should never raise a TypeError. But still it may raise other errors. Again, it depends on the function you talk about.
You were talking explicitly about the DOM and not about built-in functions. To be honest I can't find the corresponding parts of the spec. The ECMA spec is so much easier to read then the w3 website.
Won't hurt. You can even call a function with less parameters than it takes, as long as the function code is ok with a few undefined values.
I came across this important, however old, question; and I hope it'll be beneficial for future generations to share my experiments with it:
One can use the arguments object in order to access a function's arguments, regardless of the amount of arguments in the function's signature.
It's worth mentioning that this doesn't apply to arrow functions:
function singleArg(x) {
console.log(arguments);
}
singleArg(1, 2); // Called with 2 arguments
singleArg(); // Called with 0 arguments
// Results in an error, as 'arguments' isn't defined for arrow functions
((arg) => console.log(arguments))(1);
It's stated in the documentation that arguments isn't exactly an Array:
“Array-like” means that arguments has a length property and properties indexed from zero, but it doesn't have Array's built-in methods like forEach() and map().
Hence the following code results in an error:
(function singleArg(x) {
console.log(arguments); // This line works
arguments.forEach(x => console.log(x)); // This causes an error
})(1, 2);
Upon calling a function with less arguments than in its signature, they're assigned undefined:
(function twoArgs(a, b) {
console.log(`a: ${a}\nb: ${b}`);
})(1);
Try taking a look at this post and perhaps this one.
From MDN:
The arguments object is a local variable available within all
functions; arguments as a property of Function can no longer be used.
You can refer to a function's arguments within the function by using
the arguments object. This object contains an entry for each argument
passed to the function, the first entry's index starting at 0.
You can use the arguments object if you call a function with more
arguments than it is formally declared to accept. This technique is
useful for functions that can be passed a variable number of
arguments.
function myConcat(separator) {
var result = "";
// iterate through non-separator arguments
for (var i = 1; i < arguments.length; i++) {
result += arguments[i] + separator;
}
return result;
}
I don't think it will mess anything up unless you are explicitly dealing with the implicit arguments array. Why are you doing this though?
Based on some code in a lecture by Doug Crockford, I've created this.
var isAlphaUser = (function() {
alert("Forming Alpha User List");
let AlphaUsers = {
1234: true,
5678: true
};
return function(id){
alert("Checking Alpha Users:",id);
return AlphaUsers[id];};
}());
alert("starting");
alert(isAlphaUser(1234));
alert(isAlphaUser(5678));
alert(isAlphaUser(3456));
which gives me this:
Forming Alpha User List
starting
Checking Alpha Users: 1234
true
Checking Alpha Users: 5678
true
Checking Alpha Users: 3456
undefined
Which is quite cool, as it does the expensive setup once only, and every further call is a cheap check.
However, I can't decipher the code that does this. Specifically, I can't understand why I need the "()" at the end of the function declaration.
Can somebody explain how this syntax is working?
() calls a function. function() { } defines a function. Appending () right after immediately calls it1, and the result (also an anonymous function) is assigned to isAlphaUser.
The function() { ... }() pattern is frequently used to isolate variables to an inner scope, so those variables don't become part of the global scope.
In this case, this is what happens:
An anonymous function is run, defining a variable AlphaUsers inside that scope.
That function returns another function that takes 1 parameter. This function is a closure to which the AlphaUsers variable becomes bound (in other words, available). This function checks if the parameter passed in is contained in AlphaUsers (actually, it returns the item at that index, which is just a boolean).
The return value is assigned to a variable isAlphaUser.
Since isAlphaUser is now a function, it can be called to see if the parameter is contained in the AlphaUsers variable, but no direct access to AlphaUsers is available in the global scope (it become a sort of private variable).
1 — Note: As cwolves mentioned in the comments, beware that while () appended directly after the } works in this case, it is only because in this case the function definition is a function expression. If function is the first word on the line, the line becomes a function declaration, and that is all that line can do, the function is not anonymous (it will require a name, otherwise it's a syntax error) and cannot be called immediately inline. See Function Declarations vs. Function Expressions for more info.
The () at the end of the code is separate from the closure issue. By wrapping your function in parens and adding the () at the end you are creating an anonymous function that is run immediately with whatever arguments you pass into ().
Specifically, I can't understand why I need the "()" at the end of the
function declaration.
It creates self-invoking function, in other words, the function is executed as soon as it is parsed.
It is basically same thing when you call a function by suffixing it with () like:
myfunc(); // call this func
The top-level anonymous function returns the function that the isAlphasUser varaible refers to.
You need to call the top-level function, to get the inner-function reference.
Think of it like this, the outer anonymous function is a function factory, i.e., it returns a function.
In order to use any function (even one that returns a function) you must call it.