ES6: Why does my misplacement of the parenthesis still produce same result? - javascript

I noticed that I had a type in one of my forEach statements but I still got the same result.
foo = ["bobby", "tommy", "brendan"]
foo.forEach((f => {
console.log(f)
}))
vs.
foo.forEach((f) => {
console.log(f)
})
I'm curious as to why the result would be the same on the first one, which I made the typo on.

An arrow function with one argument can be written in two ways:
f => {
console.log(f)
}
And
(f) => {
console.log(f)
}
So the braces around the argument part are optional if there is only one argument.
And placing braces around a complete expression does not change anything for that expression, this:
f => {
console.log(f)
}
and this
(f => {
console.log(f)
})
or even this
((f => {
console.log(f)
}))
is identical.
Your first code block can be formatted as this for a better understanding:
foo.forEach(
// first argument of forEach
(f => {
console.log(f)
})
// end of argument list of forEach
)
So there are no misplaced braces, you just removed the optional ones around the f and place optional once around the complete expression.

foo.forEach((f => {
console.log(f)
}))
forEach accepts two paramters(first is method/function and second is optional which value to use as this object when executing callback), wrapping it around with () is not required. Although with arrow functions, if you have a single parameter you don't need to explicity wrap it with (), but you need to wrap you arguments if your method has multiple arguments.
You can check this out for further reading on arrow functions and this for forEach in js

Related

syntax explanation for copying object array and add new property

Can someone explain to me why this is the only version I've tried that works for copying state with es6 and adding another field, out of the other ways tried that are listed below? :
const values = [{key: "1", val: "one"}, {key: "2", val: "two"}];
var works = values.map(v => {
return {
...v,
extra: "stuff"
}
})
And all of these produce these errors:
//Unexpected token '...'
var notWorks1 = values.map(v => ...v, extra: "stuff");
// Rest parameter must be last formal parameter
var notWorks2 = values.map(v => {...v, extra: "stuff"})
// Rest parameter must be last formal parameter
var notWorks3 = values.map(v => {
{
...v,
extra: "stuff"
}
})
// unexpected token 'return'
var notWorks4 = values.map(v =>
return {
...v,
extra: "stuff"
}
)
// unexpected 'return'
var notWorks5 = values.map(v => return ...v, extra: "stuff");
I thought the arrow was implicit return (see first 3 attempts).
Is that first way the only syntax that can be used? If there are any others, I'd like to know as I'm trying to practice and learn multiple options.. and I want the most terse, smallest option (one line).
The answer of #Bulent is correct, but I'd like to add some more information:
//Unexpected token '...'
var notWorks1 = values.map(v => ...v, extra: "stuff");
This syntax doesn't make sense. As #Bulent says, the spread syntax (...) can only be used inside object literals ({ ...v }), array literals ([ ...v ], only if v is an array) or function calls (f( ...v ), again only if v is an array).
// Rest parameter must be last formal parameter
var notWorks2 = values.map(v => {...v, extra: "stuff"})
The problem here is that in JavaScript braces ({, }) have two functions: either for object literals, as you are trying to use here, but also for code blocks, for example around the body of a function. In this case JavaScript is expecting the braces to be the body of the arrow function. What needs to be done is change the context so that an expression (which an object literal is) is expected. This can for example be done by putting the object literal in round brackets:
var notWorks2 = values.map(v => ({...v, extra: "stuff"}))
// Rest parameter must be last formal parameter
var notWorks3 = values.map(v => {
{
...v,
extra: "stuff"
}
})
Again the first pair of braces is consider a (function body) block, and inside a block braces are again expected to be another block. This time wrapping the object literal in round brackets wouldn't do anything, because an expression alone does nothing inside a function body. Instead you have to use return.
// unexpected token 'return'
var notWorks4 = values.map(v =>
return {
...v,
extra: "stuff"
}
)
Arrow functions can consist of either an expression (no braces) or a function body block (with braces). A return statement isn't an expression, so this doesn't work. return statements can only be used inside a function body block.
One final point: Avoid using var. It is outdated. Use const or let instead.
spread syntax is used in an array or object. So you have to put it between {} or [].
{} are compiled as if they belong to the arrow function, not an object.
When you put your code in {}, you need to return the result.
In order to use return in arrow function, you need the put it between {}
The same as 4.

Javascript: Different behavior with single-argument Array.map() depending on whether I use curly braces or not (aren't both forms allowed?)

I'm experimenting with Array.map() and got this little snippet, which does perform as intended:
let cities = ["Buenos Aires", "Santa Fe", "Mar del Plata", "Mar de las Pampas"];
function urlify(string) {
return string.split(" ").join("-").toLowerCase();
}
function functionalUrl(elements) {
return elements.map( element => urlify(element) );
}
console.log(functionalUrl(cities));
// ['buenos-aires', 'santa-fe', 'mar-del-plata', 'mar-de-las-pampas' ]
However, if I replace
return elements.map( (element) => urlify(element) );
with
return elements.map( (element) => { urlify(element); } );
(i.e., add parentheses and curly braces) it returns
[undefined, undefined, undefined, undefined]
I don't understand such behavior, as the curly braces/parentheses form is supposed to be "correct", and taking them away (I thought?) is just allowed in the specific case of a single-argument function...
What am I missing here?
Thanks!
elements.map( (element) => { urlify(element); } );
When you do the above code, you are creating the function body (assuming there are more lines of code to be included) and it expects the 'return' keyword, but if you are returning a single value (the result of one single computation), in your case
elements.map( (element) => urlify(element) );
then you don't have to specify the return keyword.
So the correct code for the second scenario using braces will be
elements.map( (element) => {return urlify(element)} );
The first one is a shorthand syntax not using the return keyword, also if you just have only one parameter you don't have to wrap the parameter inside the parenthesis.
So the more concise way should be
elements.map( element => urlify(element) );

What do parenthesis surrounding brackets in the return statement of an ES6 arrow function do?

For example in redux actions, I've seen in someone's code:
export const updateMessage = text => {
return (dispatch) => {
dispatch(updateChatMessage(text))
}
}
and:
const updateChatMessage = text => ({
type: types.someActionType,
text
})
it seems to function as an imply a return but I thought that was already implied in an arrow functions brackets following the fat arrow.
What do the parenthesis ({...}) do? are they necessary? Is there an alternate way to accomplish the same thing?
when you write myFunction = value => ({prop: value})
it return the object {prop: value}, in this case {} are object delimiter and not 'function delimiter'
const updateChatMessage = text => ({
type: types.someActionType,
text
})
another eg :
when you want to multiply by two each elem of an array you can write :
array.map(elem => {return elem * 2})
or
array.map(elem => elem * 2) //same result
and if you want an eg with () that wrap an object litteral :
let array = [{val: 2},
{val: 4},
{val: 8},
{val: 16}];
let output = array.map( ({val}) => ({val: val*2}) );
console.log(output);
If you wrap the brackets with parenthesis you are making your function return an object literal (thus you don't need the return keyword). If you don't use parenthesis you have to use the return keyword.
As per the arrow function docs,
// Parenthesize the body of a function to return an object literal expression:
params => ({foo: bar})
That means if you want to return an object implicitly you have to wrap it in parentheses.
Without this, code inside braces will be considered as function body and not an object (as you'd want)
Following are equivalent:
params => { return {foo: bar}} // Explicitly return an object (from function body)
params => ({foo: bar}) // Implicitly return an object by wrapping it with parentheses
In the first example, the {} are used to identify multiple lines of code, which is why the return is required in order to obtain something other than undefined.
In the second example, the {} are used to create an object.

Unexpected token, expected "," while looping through objects

I'm trying to map through collection of objects inside an object and access the color item, but i get an error Unexpected token, expected ",". This is how i'm trying to map through. Is this the right way to map objects to retrieve value from colors.
{Object.keys(this.state.lists).map((item, i) =>
(this.state.lists[item].colors).map(item, i) =>
<li key={i}>{this.state.lists[item].colors[item]} </li>
)}
this.state.lists looks like this:
{{id: 1, colors:["red", "blue"]}, {id: 2, colors:["green", "yellow"]}}
You are not passing a callback function to your second map call, .map(item, i). Hence the syntax error. It should instead be something like .map((item, i) => ...).
Here's some cleaned up code that might make sense of this, though I haven't tested if it works with React:
const colors = Object.keys(this.state.lists).map(itemKey => {
return <li key={itemKey}>{this.state.lists[itemKey].colors[0]}</li>
})
And when you render,
<ul>{colors}</ul>
When using ES6 functions, you can omit the () of the parameters, only if you use 1 parameter. What you've done is actually closed your map before you even got to the fat arrow (=>). Your error is saying it doesn't understand the , in map(item, i), since map doesn't accept a second parameter. Here's a bit of a break-down, followed by some optimized code for your problem.
A basic ES6 function is () => {}, where the parameters go between the () braces, and the code goes between the {}.
Here's a basic sum function: (a, b) => { return a+b }. Since this only has one line, and it's the return value, you can omit the {} brackets. i.e., (a, b) => a+b
Here's a hello function: (name) => { return 'hello ' + name }. Since it only has 1 parameter, you can use name => { return 'hello ' + name }. Or even using the above rule: name => 'hello ' + name.
These shortcuts can make code easier to write, but perhaps more difficult to understand. If in doubt, just always keep the () braces to avoid confusion.
const obj = {
1: {id: 1, colors:["red", "blue"]},
2: {id: 2, colors:["green", "yellow"]}
}
for (key in obj) {
const item = obj[key];
item.colors.map((color, i) => {
console.log( `<li key=${item.id}-${i}>${color}</li>`)
// Below lines are commented out because StackOverflow
// does not process JSX tags. Just uncomment and remove
// the console.log above
// return (
// <li key={item.id}-${i}>{color}</li>
// )
});
}
NOTES: Instead of using Object.keys to get an array of keys, I just use a for...in loop to accomplish the same thing.
Documentation
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

curly braces in es6 arrow function for each [duplicate]

This question already has answers here:
Arrow function without curly braces
(9 answers)
Closed 4 years ago.
We create presentational component or stateless component like this
const MyComponent = () => {
return(<div>my component</div>)
}
but I'd seen this
const MyComponent = () =>
<div>
<h1>head</h1>
my component
</div>
so now I'm confused when the braces is needed when using es6's arrow function.
This confused me on when rendering a list using map
shorter version
<div>
{map(o =>
<div>{o.name}</div>
)}
</div>
longer version
<div>
{map(o => {
return(<div>{o.name}</div>)
})}
</div>
Both are correct, but why write longer?
{map(o => // without curly brackets
<div>{o.name}</div> // this will be returned implicitly
)}
{map(o => { // with curly brackets
return <div>{o.name}</div> // you need to return explicitly
}
)}
If you do curly brackets ,
You have to explicilty return the data ,
When to use which one?
When you have mutliple line of execution you need to do curly brackets and return from it
But if you have single line of execution, that you need to return , then there is no need of curly brackets and return , it will return implicitly.
Same as If condition
if(true)
// do this for single line
else
// do this for single line
if() {
// do this for multiple line
} else {
// do this for multiple line
}
Arrow functions work both way to provide you with a bit of versatility. Say you need to perform some logic inside your function before you return, in this case you would need to add curly braces, i.e say you need to extract the name of a list of users, but you want to append their title.
let users = [new User(), ... ];
//...
let withTitle = users.map(p => {
const title = getTitle(p); // automagically returns Mr, Mrs, etc
return `${title} ${p.fullName}`
});
// withTitle => ['Mr Ricky Bobby', 'Mr Ron Burgundy']
Now, you can declare a function that does the work for you, and use the shorthand version of the arrow function. like so.
const extractWithTitle: (user) => {
const title = getTitle(p); // automagically returns Mr, Mrs, etc
return `${title} ${p.fullName}`
}
let withTitle = users.map(p => extractWithTitle(p));
// withTitle => ['Mr Ricky Bobby', 'Mr Ron Burgundy']
Now, an even shorter way to approach this would be to pass a reference to the function.
users.map(extractWithTitle);
Both are correct, but why write longer?
You basically need to use the longer version if you need to add more sentences in you arrow function other than the jsx component.
E.g.
<div>
{map(o => {
const name = "My name is: " + o.name;
return(<div>{name}</div>)
})}
</div>
Otherwise, you may use the short version.

Categories

Resources