This question already has an answer here:
Why doesn't my arrow function return a value?
(1 answer)
Closed 4 years ago.
So to my understanding which is obviously wrong at this moment in time is that,
return arg => arg*2
is the same as
return (arg)=>{arg*2}
I always assumed arrow functions are just syntactically neater.
But doing this with closures like so doesn't work.
function addTwoDigits(firstDigit){
return (secondDigit)=>{firstDigit + secondDigit}
}
let closure = addTwoDigits(5);
console.log(closure(5)) // Undefined
Yet this is fine
function addTwoDigitsV2(firstDigit){
return secondDigit => firstDigit + secondDigit
}
let closure2 = addTwoDigitsV2(10);
console.log(closure2(10))// 20
arrow function works differently here:-
(x)=> x*2 ; // dont have to return anything, x*2 will be returned
is not same as
(x) =>{x*2}
//here you need to return something otherwise undefined will be returned
When you use {} you must set return
return (arg)=>{return arg*2}
The arrow function only supplies the return automatically if you have an expression after the arrow. If the arrow is followed by a curly brace, it's treated as the braces around a function body, so you have to write return explicitly, i.e.
arg => arg * 2
is equivalent to:
(arg) => { return arg * 2; }
function addTwoDigits(firstDigit) {
return (secondDigit) => {
return firstDigit + secondDigit
}
}
let closure = addTwoDigits(5);
console.log(closure(5))
You need a return statement if the body of your arrow function is wrapped in { ... }.
Since yours is a single expression, you can skip the {-} and return. But if you have the {-}, you need the return statement.
The parentheses are not an issue here. You need them if you have more than a single parameter. With one, they're optional.
Related
I'm new to both ES6 and React and I keep seeing arrow functions. Why is it that some arrow functions use curly braces after the fat arrow and some use parentheses?
For example:
const foo = (params) => (
<span>
<p>Content</p>
</span>
);
vs.
const handleBar = (e) => {
e.preventDefault();
dispatch('logout');
};
The parenthesis are returning a single value, the curly braces are executing multiple lines of code.
Your example looks confusing because it's using JSX which looks like multiple "lines" but really just gets compiled to a single "element."
Here are some more examples that all do the same thing:
const a = (who) => "hello " + who + "!";
const b = (who) => ("hello " + who + "!");
const c = (who) => (
"hello " + who + "!"
);
const d = (who) => (
"hello "
+ who
+ "!"
);
const e = (who) => {
return "hello " + who + "!";
};
You will also often see parenthesis around object literals because that's a way to avoid the parser treating it as a code block:
const x = () => {} // Does nothing
const y = () => ({}) // returns an object
One can also use curly braces to prevent a single line arrow function from returning a value -- or to make it obvious to the next developer that a single line arrow function shouldn't, in this case, be returning anything.
For example:
const myFunc = (stuff) => { someArray.push(stuff) }
const otherFunc = (stuff) => someArray.push(stuff)
console.log(myFunc()) // --> logs undefined
console.log(otherFunc()) // --> logs result of push which is new array length
Parenthesis are used in an arrow function to return an object.
() => ({ name: 'YourName' }) // This will return an object
That is equivalent to
() => {
return { name : 'YourName' }
}
Actually in a briefcase when somebody uses braces in an arrow function declaration, it is equal to below:
const arrow = number => number + 1;
|||
const arrow = (number) => number + 1;
|||
const arrow = (number) => ( number + 1 );
|||
const arrow = (number) => { return number + 1 };
Parenthesis has an implicit return statement while curly braces you need an explicit return statement
If you use curly braces after the arrow to define the function body, you have to use the 'return' keyword to return something.
For example:
const myFun1 = (x) => {
return x;
}; // It will return x
const myFun2 = (x) => {
x;
}; // It will return nothing
If you use the parenthesis, you don't need to mention the 'return' keyword.
For example:
const myFunc1 = (x) => x; // It will return x
const myFunc2 = (x) => (x); // It will also return x
In your first example, the right-hand side of the arrow function shows a single expression that is enclosed by a grouping operator:
const foo = (params) => (
<span>
<p>Content</p>
</span>
);
A similar comparable case would be the following:
const foo = (params) => (<span><p>Content</p></span>);
A distinction, in the above cases using single expressions, is that the right-hand side is the returned value of the function.
On the other hand, if you use curly braces, JavaScript will understand that as a statement:
const foo = (params) => {} // this is not an object being returned, it's just an empty statement
Therefore, using statement is a good start for you to have code in it, multiple lines, and it will require the use of "return" if the function is intended to return value:
const foo = (params) => {
let value = 1;
return value;
}
In case you wanted to return an empty object in the shortest form:
const foo = (params) => ({})
See tests
To answer a duplicate post(question posted here), just for reference for others:
var func = x => x * x;
// concise body syntax, implied "return"
var func = (x, y) => { return x + y; };
// with block body, explicit "return" needed
For reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Function_body
Also note:
If you are returning an object literal as the result from a fat arrow function, then you must enclose the object in parentheses, e.g., myFunc = () => ({ data: "hello"}). You will receive an error if you omit the parentheses because the build tools will assume that the curly braces of the object literal are the start and end of a function body.
Every function has 2 aspects.
First of them is that each one, not just the arrow functions, has an execution context (a block scope) in which the variables are created and used.
In other words, inside the curly braces { ... } of the function, what is declared and assigned there, stays there and is not visible to the outside functions / or variables.
For example, when writing something as
let x = 100;
function doSomething() {
let x = 50;
console.log(x);
}
doSomething(); // 50
console.log(x); // 100
both values are displayed in console (instead of 'x from outside just being replaced by x from inside the function').
You see that despite of let not usually allowing other variable x to be declared again (with the same name x), in this case, because the second x is declared and initialized inside the { ... }, it does not alter the outside one, which also happens because after the function doSomething is called, the x from inside of it is created, assigned, printed in console and then destroyed (deleted from the memory). So that process happens every time we call that function by running doSomething() .
So this is the first aspect to take into consideration when understanding the functions: they execute then forget the values created by the code inside their curly braces.
Because of it, it's easier to understand their second aspect -- as functions cannot just work isolated from the others, they need to also send data to the others, so they have some 'reporting aspect' used to externalize some part of the results computed inside their curly braces, which is exactly why the return statement exists.
Return exists in each function, even in the console.log or alert(), even in doSomething(), but in these cases where we didn't explicitly set something for it, it is always 'return undefined'.
Therefore it isn't necessary to write it, but instead know that where you don't return something specific, the function itself will do it for you by returning undefined.
When you write (or use) a function meant just to execute something, it will also return undefined. Always.
You can check that thing with every function which (apparently) has no declared return:
let x = alert(100);
console.log(x); // undefined
let y = doSomething(); // console prints 50
console.log(y); // 50, then undefined --- 2 lines
console.log(alert('Hello')); // undefined
console.log(console.log('Okay')); // Okay , then undefined
Why is that?
Because alert() which is a method of global object window (in browser) (so it is actually window.alert() ) and also console.log() (which is the same with window.console.log() , too), execute something (printing in an alert box or in the console whatever is in between the () AND THEN return undefined).
Now, coming back to the arrow functions, they are not just some new way of notation for writing the functions but they also have some specific features.
First, if you only have a parameter between the () in an arrow function, you can write it without the parentheses.
Second, if inside the curly braces there's a single statement, you can omit as well the curly braces.
Third one, if the single statement is a return statement, you can omit the word return.
Somehow, using these we could transform many usual functions into arrow functions if needed:
function doSomething() {let x = 50; console.log(x);} // as function declaration
let doSomething = function() {let x = 50; console.log(x);}; // as function expression, which is an anonymous function assigned to the variable 'doSomething'
let doSomething = () => {let x = 50; console.log(x);}; // as arrow function
// let's transform it further
let doSomething = () => {console.log(50)}; //
// that is equivalent to ---- let doSomething = () => {console.log(50); return undefined};
// or even to ---- let doSomething = () => {return ( console.log(50) ) };
// because anyways, *console.log* has *return undefined* in it, as explained above
//which is the same as ---- let doSomething = () => {return console.log(50) };
// let's now apply the rules 2 and 3 from above, one by one:
let doSomething = () => return console.log(50);
let doSomething = () => console.log(50);
// Obviously, this just shows how we could rewrite many usual functions (functions declarations) into arrow functions
// we can do that safely if we don't have any **this** involved in the functions, of course
// also, from all lines of code above only one must remain, for example the last one.
// the last one, despite only having ---- console.log(50) --- as the execution aspect, it also ---- returns undefined ---- as well
// obviously ---- console.log( typeof doSomething ); // function
// while ---- console.log( typeof doSomething() ); // undefined
If an arrow function has 2 or more parameters, we cannot omit the parentheses around them:
function sum(a, b) {let total = a + b; return total}
let sum = function(a, b) {let total = a + b; return total};
// or
let sum = (a, b) => {let total = a + b; return total};
// or
let sum = (a, b) => {return a + b};
// or
let sum = (a, b) => a + b;
For simple operations as above, the fat arrow sign '=>' can be "read" as is transformed into, in other words, a and b is (are) transformed into a + b.
Opposite to that, there are also functions that validate some data (for example checking the data type, etc), like this one
let isNumber = x => typeof x === "number";
// or
let isNumber = (x) => {return (typeof x === "number")};
// obviously,
isNumber("Hello, John!"); // false
Those DON'T transform the data, and thus the arrow sign can be read something more as with the condition that, or similar.
In other words, a function like
let double = x => x * 2 // 'double' is a function that transforms x into x*2
is not the same as a checking one (mostly used in filters, sort, and other kind of validating functions, usually as callback function, etc)
let isArray = arr => Array.isArray(arr) // that last one already returns boolean by itself, no need to write return (Array.isArray() etc)
Last thing to know about return is that when you write code in multiple lines, the ASI (Automatic Semicolon Insertion) will insert a ';' after return if you mistakenly press enter after writing the return word, which will break the code, therefore instead of
return
a+b;
your code will behave as
return;
a+b;
so you better write the code with parentheses as here:
return (
a + b
);
as explained in MDN website here, too.
I'm shortening a function expression to an arrow function expression.
When can I remove the curly brackets of the function? Can you always or is there a rule when you're allowed?
I see on (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) it says you can drop curly brackets when you use just a single expression:
However, I understood the following to be 2 expressions, and the absence of curly brackets doesn't stop the function from running. It does still create an implicit return and just returns the first expression. Is this all I need to know about getting rid of curly brackets in arrow function expressions?
f = () => x = 5 * 5; this;
console.log(f());
Check out this article on MDN on arrow functions MDN Arrow functions
What I believe you are talking about is an implicit return.
If you remove the curly braces from an arrow function it is implied that you will return what ever the code tells it to do
let implicitAddFunc = (arg) => arg + 2;
In this example you do not need to explicitly declare what you are returning from the function. When you are using curly braces you must actually call out what you are returning
let nonImplicitAddFunc = (arg) => {
let returnValue;
returnValue = arg + 2
//With curly brace must have the keyword *return*
return returnValue
}
For a deeper dive please reference this post When should I use `return` in es6 Arrow Functions?
On this example you need a square brackets because you need to do something in function body:
const data = {a: 1, b: 2};
const functionWithReturn = () => {
const newData = {
...data,
c: 3
}
return newData;
}
This is shortcut for return (which doing exactly the same as previous):
const functionShort = () => ({
...data,
c: 3
})
The only difference that on the first example you can do something else inside function (like calling another function, make some data mutation...).
This question already has answers here:
Curly Brackets in Arrow Functions
(3 answers)
Closed 2 years ago.
I have a .map() function that changes isActive property value of objects in data array. However wraps it with curly braces returns me undefined whereas wrapping it with parenthesis or no wrap returns the updated value. Curly braces are used as a wrapper in an arrow function but does it work differently for .map()?
const newData = data.map((data) => {
data.label === label ? { ...data, isActive: !data.isActive } : data,
});
console.log(newData)
//undefined
const newData = data.map((data) =>
data.label === label ? { ...data, isActive: !data.isActive } : data,
);
console.log(newData)
//returns updated newData
That’s the behavior of arrow function. Arrow function syntax is designed to be terse.
(arg) => [single expression]
If what follows the arrow is one single expression without curly braces, it implies returning the value of that expression. The return keyword is omitted.
If wrapping curly braces follows the arrow, then what goes inside the braces are treated as normal function body, and return keyword must be used if you mean to return a value.
So (x) => x + 1 is translated to:
function (x) {
return x + 1;
}
And (x) => { x + 1 } is translated to:
function (x) {
x + 1;
}
I must also add that (x) => ({ x }) is translated to:
function (x) {
return { x: x };
}
Curly brace {...} can mean an object literal, a function body or a code block.
In order to disambiguate, you need to put parenthesis around the braces to tell the parser to interpret {...} as an “object literal expression”.
I'm learning javascript and I found this exercise:
function abc(a){
return(function(y){
return y--**--y+1;
})(++a)+a;
}
document.write(abc(2));
The output of that is 7 and I dont understand why, I searched information about nested functions and I didnt found anything....
How is "y" defined?
this function translates to:
//I've replaced the arguments and the vars with the actual values
function abc(){
function innerFunction(){
return (3 ** 1) + 1
}
return innerFunction(3) + 3
}
//or written differently
function abc(a){
function innerFunction(v){
//v--
var tmp1 = v;
v = v-1;
//--v
v = v-1;
var tmp2 = v;
return Math.pow(tmp1, tmp2) + 1;
}
a = a+1; //++a
return innerFunction(a) + a;
}
That is easy.
Function abc return (function(y){ return y--**--y+1; })(++a)+a
this means if a is 2 (function(3){ return y--**--y+1; }) + 2
This contains an immediately invoked function expression (IIFE).
Here's an example that might clarify how they work:
(function(x) { return x; })(10); // Returns 10
The value inside the parenthesis is used as the function's argument as soon as the function is defined. So, in this case, the function is set to return the argument, and immediately afterwards, it is given the value 10.
On your example, with some added whitespace:
return (function(y) {
return y-- ** --y + 1;
})(++a)
+ a
What's happening is the same. A function is being defined then, immediately afterwards, it receives the argument ++a. It will replace all instances of y by the value contained in ++a. Then, as that is returned, it goes through + a, so it adds a to the result.
I'm new to both ES6 and React and I keep seeing arrow functions. Why is it that some arrow functions use curly braces after the fat arrow and some use parentheses?
For example:
const foo = (params) => (
<span>
<p>Content</p>
</span>
);
vs.
const handleBar = (e) => {
e.preventDefault();
dispatch('logout');
};
The parenthesis are returning a single value, the curly braces are executing multiple lines of code.
Your example looks confusing because it's using JSX which looks like multiple "lines" but really just gets compiled to a single "element."
Here are some more examples that all do the same thing:
const a = (who) => "hello " + who + "!";
const b = (who) => ("hello " + who + "!");
const c = (who) => (
"hello " + who + "!"
);
const d = (who) => (
"hello "
+ who
+ "!"
);
const e = (who) => {
return "hello " + who + "!";
};
You will also often see parenthesis around object literals because that's a way to avoid the parser treating it as a code block:
const x = () => {} // Does nothing
const y = () => ({}) // returns an object
One can also use curly braces to prevent a single line arrow function from returning a value -- or to make it obvious to the next developer that a single line arrow function shouldn't, in this case, be returning anything.
For example:
const myFunc = (stuff) => { someArray.push(stuff) }
const otherFunc = (stuff) => someArray.push(stuff)
console.log(myFunc()) // --> logs undefined
console.log(otherFunc()) // --> logs result of push which is new array length
Parenthesis are used in an arrow function to return an object.
() => ({ name: 'YourName' }) // This will return an object
That is equivalent to
() => {
return { name : 'YourName' }
}
Actually in a briefcase when somebody uses braces in an arrow function declaration, it is equal to below:
const arrow = number => number + 1;
|||
const arrow = (number) => number + 1;
|||
const arrow = (number) => ( number + 1 );
|||
const arrow = (number) => { return number + 1 };
Parenthesis has an implicit return statement while curly braces you need an explicit return statement
If you use curly braces after the arrow to define the function body, you have to use the 'return' keyword to return something.
For example:
const myFun1 = (x) => {
return x;
}; // It will return x
const myFun2 = (x) => {
x;
}; // It will return nothing
If you use the parenthesis, you don't need to mention the 'return' keyword.
For example:
const myFunc1 = (x) => x; // It will return x
const myFunc2 = (x) => (x); // It will also return x
In your first example, the right-hand side of the arrow function shows a single expression that is enclosed by a grouping operator:
const foo = (params) => (
<span>
<p>Content</p>
</span>
);
A similar comparable case would be the following:
const foo = (params) => (<span><p>Content</p></span>);
A distinction, in the above cases using single expressions, is that the right-hand side is the returned value of the function.
On the other hand, if you use curly braces, JavaScript will understand that as a statement:
const foo = (params) => {} // this is not an object being returned, it's just an empty statement
Therefore, using statement is a good start for you to have code in it, multiple lines, and it will require the use of "return" if the function is intended to return value:
const foo = (params) => {
let value = 1;
return value;
}
In case you wanted to return an empty object in the shortest form:
const foo = (params) => ({})
See tests
To answer a duplicate post(question posted here), just for reference for others:
var func = x => x * x;
// concise body syntax, implied "return"
var func = (x, y) => { return x + y; };
// with block body, explicit "return" needed
For reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Function_body
Also note:
If you are returning an object literal as the result from a fat arrow function, then you must enclose the object in parentheses, e.g., myFunc = () => ({ data: "hello"}). You will receive an error if you omit the parentheses because the build tools will assume that the curly braces of the object literal are the start and end of a function body.
Every function has 2 aspects.
First of them is that each one, not just the arrow functions, has an execution context (a block scope) in which the variables are created and used.
In other words, inside the curly braces { ... } of the function, what is declared and assigned there, stays there and is not visible to the outside functions / or variables.
For example, when writing something as
let x = 100;
function doSomething() {
let x = 50;
console.log(x);
}
doSomething(); // 50
console.log(x); // 100
both values are displayed in console (instead of 'x from outside just being replaced by x from inside the function').
You see that despite of let not usually allowing other variable x to be declared again (with the same name x), in this case, because the second x is declared and initialized inside the { ... }, it does not alter the outside one, which also happens because after the function doSomething is called, the x from inside of it is created, assigned, printed in console and then destroyed (deleted from the memory). So that process happens every time we call that function by running doSomething() .
So this is the first aspect to take into consideration when understanding the functions: they execute then forget the values created by the code inside their curly braces.
Because of it, it's easier to understand their second aspect -- as functions cannot just work isolated from the others, they need to also send data to the others, so they have some 'reporting aspect' used to externalize some part of the results computed inside their curly braces, which is exactly why the return statement exists.
Return exists in each function, even in the console.log or alert(), even in doSomething(), but in these cases where we didn't explicitly set something for it, it is always 'return undefined'.
Therefore it isn't necessary to write it, but instead know that where you don't return something specific, the function itself will do it for you by returning undefined.
When you write (or use) a function meant just to execute something, it will also return undefined. Always.
You can check that thing with every function which (apparently) has no declared return:
let x = alert(100);
console.log(x); // undefined
let y = doSomething(); // console prints 50
console.log(y); // 50, then undefined --- 2 lines
console.log(alert('Hello')); // undefined
console.log(console.log('Okay')); // Okay , then undefined
Why is that?
Because alert() which is a method of global object window (in browser) (so it is actually window.alert() ) and also console.log() (which is the same with window.console.log() , too), execute something (printing in an alert box or in the console whatever is in between the () AND THEN return undefined).
Now, coming back to the arrow functions, they are not just some new way of notation for writing the functions but they also have some specific features.
First, if you only have a parameter between the () in an arrow function, you can write it without the parentheses.
Second, if inside the curly braces there's a single statement, you can omit as well the curly braces.
Third one, if the single statement is a return statement, you can omit the word return.
Somehow, using these we could transform many usual functions into arrow functions if needed:
function doSomething() {let x = 50; console.log(x);} // as function declaration
let doSomething = function() {let x = 50; console.log(x);}; // as function expression, which is an anonymous function assigned to the variable 'doSomething'
let doSomething = () => {let x = 50; console.log(x);}; // as arrow function
// let's transform it further
let doSomething = () => {console.log(50)}; //
// that is equivalent to ---- let doSomething = () => {console.log(50); return undefined};
// or even to ---- let doSomething = () => {return ( console.log(50) ) };
// because anyways, *console.log* has *return undefined* in it, as explained above
//which is the same as ---- let doSomething = () => {return console.log(50) };
// let's now apply the rules 2 and 3 from above, one by one:
let doSomething = () => return console.log(50);
let doSomething = () => console.log(50);
// Obviously, this just shows how we could rewrite many usual functions (functions declarations) into arrow functions
// we can do that safely if we don't have any **this** involved in the functions, of course
// also, from all lines of code above only one must remain, for example the last one.
// the last one, despite only having ---- console.log(50) --- as the execution aspect, it also ---- returns undefined ---- as well
// obviously ---- console.log( typeof doSomething ); // function
// while ---- console.log( typeof doSomething() ); // undefined
If an arrow function has 2 or more parameters, we cannot omit the parentheses around them:
function sum(a, b) {let total = a + b; return total}
let sum = function(a, b) {let total = a + b; return total};
// or
let sum = (a, b) => {let total = a + b; return total};
// or
let sum = (a, b) => {return a + b};
// or
let sum = (a, b) => a + b;
For simple operations as above, the fat arrow sign '=>' can be "read" as is transformed into, in other words, a and b is (are) transformed into a + b.
Opposite to that, there are also functions that validate some data (for example checking the data type, etc), like this one
let isNumber = x => typeof x === "number";
// or
let isNumber = (x) => {return (typeof x === "number")};
// obviously,
isNumber("Hello, John!"); // false
Those DON'T transform the data, and thus the arrow sign can be read something more as with the condition that, or similar.
In other words, a function like
let double = x => x * 2 // 'double' is a function that transforms x into x*2
is not the same as a checking one (mostly used in filters, sort, and other kind of validating functions, usually as callback function, etc)
let isArray = arr => Array.isArray(arr) // that last one already returns boolean by itself, no need to write return (Array.isArray() etc)
Last thing to know about return is that when you write code in multiple lines, the ASI (Automatic Semicolon Insertion) will insert a ';' after return if you mistakenly press enter after writing the return word, which will break the code, therefore instead of
return
a+b;
your code will behave as
return;
a+b;
so you better write the code with parentheses as here:
return (
a + b
);
as explained in MDN website here, too.