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.
This question already has answers here:
Arrow function without curly braces
(9 answers)
Curly Brackets in Arrow Functions
(3 answers)
Closed 4 years ago.
What's the difference between these two in javascript? what does it mean in scripting?
const Test1 = () => {
console.log('test1')
}
const Test2 = () => (
console.log('test2')
)
The "basic" form is with curly braces, just like regular functions:
() => {
...
}
However, arrow functions allow one special case shorthand:
() => plain expression
If you don't use curly braces, you may use one plain expression instead, with an implicit return. I.e. these two are equivalent:
() => { return 42; }
() => 42
So your version using parentheses counts as the single expression version and the return value of console.log will be returned (which is undefined either way though), whereas it won't on the version using curly braces.
Second example used to simplify returning of function, but in this case you can use only one expression, so you cannot write large of code. Try to run this example to better understand:
const Test1 = () => {
'test1'
}
console.log(Test1())
const Test2 = () => ( test = 'test4')
console.log(Test2())
Also this declaration method uses to simplify returning objects:
const Test3 = () => ({ a: 1, b: 2 });
console.log(Test3());
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 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.
This question already has answers here:
ECMAScript 6 arrow function that returns an object
(6 answers)
What does the arrow function with a () after means? [duplicate]
(3 answers)
ES6 Fat Arrow and Parentheses `(...) => ({...})` [duplicate]
(2 answers)
What does arrow function '() => {}' mean in Javascript? [duplicate]
(2 answers)
Closed 5 years ago.
I've seen JavaScript code such as this:
let a = () => ({ id: 'abc', name: 'xyz' })
What do the parentheses ( … ) wrapping the object refer to in this instance? Is it a shorthand for return?
No. Those parentheses produce an object literal. Arrow functions have many syntaxes, one of which is:
( … ) => expression
This will implicitly return an expression, for example:
() => 1 + 1
This function will implicitly return 1 + 1, which is 2. Another one is this:
( … ) => { … }
This will create a block to house multiple statements if you don't want to implicitly return an expression, and if you want to do intermediate calculations or not return a value at all. For example:
() => {
const user = getUserFromDatabase();
console.log(user.firstName, user.lastName);
}
The problem arises when you want to implicitly return an object literal. You can't use ( … ) => { … } because it'll be interpreted as a block. The solution is to use parentheses.
The parentheses are there for the { … } to be interpreted an object literal, not a block. In the grouping operator, ( … ), only expressions can exist within them. Blocks are not expressions but object literals are, thus an object literal is assumed. Thus, instead of creating a block, it will use this syntax:
( … ) => expression
And implicitly return an object literal. Without the parentheses, it will be interpreted as labels and strings, not keys and values of an object literal.
let a = () => {
id: 'abc', //interpreted as label with string then comma operator
name: 'xyz' // interpreted as label (throws syntax error)
}
The comma here would be interpreted as the comma operator, and since the operands must be expressions, and labels are statements, it will throw a syntax error.
It allows you to create an expression, so
let a = () => ({ id: 'abc', name: 'xyz' })
specifies that a when invoked, returns the enclosed object
If you remove the () in this case, it will throw an error because it is not a valid function body statement, because the {} in let a = () => { id: 'abc', name: 'xyz' } are interpreted as the boundaries of a statement, but the content inside is not valid if you look at it.
let a = () => {
id: 'abc', /* Not valid JS syntax */
name: 'xyz'
}