Related
What does the ... do in this React (using JSX) code and what is it called?
<Modal {...this.props} title='Modal heading' animation={false}>
That's property spread notation. It was added in ES2018 (spread for arrays/iterables was earlier, ES2015), but it's been supported in React projects for a long time via transpilation (as "JSX spread attributes" even though you could do it elsewhere, too, not just attributes).
{...this.props} spreads out the "own" enumerable properties in props as discrete properties on the Modal element you're creating. For instance, if this.props contained a: 1 and b: 2, then
<Modal {...this.props} title='Modal heading' animation={false}>
would be the same as
<Modal a={this.props.a} b={this.props.b} title='Modal heading' animation={false}>
But it's dynamic, so whatever "own" properties are in props are included.
Since children is an "own" property in props, spread will include it. So if the component where this appears had child elements, they'll be passed on to Modal. Putting child elements between the opening tag and closing tags is just syntactic sugar — the good kind — for putting a children property in the opening tag. Example:
class Example extends React.Component {
render() {
const { className, children } = this.props;
return (
<div className={className}>
{children}
</div>
);
}
}
ReactDOM.render(
[
<Example className="first">
<span>Child in first</span>
</Example>,
<Example className="second" children={<span>Child in second</span>} />
],
document.getElementById("root")
);
.first {
color: green;
}
.second {
color: blue;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Spread notation is handy not only for that use case, but for creating a new object with most (or all) of the properties of an existing object — which comes up a lot when you're updating state, since you can't modify state directly:
this.setState(prevState => {
return {foo: {...prevState.foo, a: "updated"}};
});
That replaces this.state.foo with a new object with all the same properties as foo except the a property, which becomes "updated":
const obj = {
foo: {
a: 1,
b: 2,
c: 3
}
};
console.log("original", obj.foo);
// Creates a NEW object and assigns it to `obj.foo`
obj.foo = {...obj.foo, a: "updated"};
console.log("updated", obj.foo);
.as-console-wrapper {
max-height: 100% !important;
}
... are called spread attributes which, as the name represents, it allows an expression to be expanded.
var parts = ['two', 'three'];
var numbers = ['one', ...parts, 'four', 'five']; // ["one", "two", "three", "four", "five"]
And in this case (I'm going to simplify it).
// Just assume we have an object like this:
var person= {
name: 'Alex',
age: 35
}
This:
<Modal {...person} title='Modal heading' animation={false} />
is equal to
<Modal name={person.name} age={person.age} title='Modal heading' animation={false} />
So in short, it's a neat short-cut, we can say.
The three dots represent the spread operator in ES6. It allows us to do quite a few things in JavaScript:
Concatenate arrays
var shooterGames = ['Call of Duty', 'Far Cry', 'Resident Evil'];
var racingGames = ['Need For Speed', 'Gran Turismo', 'Burnout'];
var games = [...shooterGames, ...racingGames];
console.log(games) // ['Call of Duty', 'Far Cry', 'Resident Evil', 'Need For Speed', 'Gran Turismo', 'Burnout']
Destructuring an array
var shooterGames = ['Call of Duty', 'Far Cry', 'Resident Evil'];
var [first, ...remaining] = shooterGames;
console.log(first); //Call of Duty
console.log(remaining); //['Far Cry', 'Resident Evil']
Combining two objects
var myCrush = {
firstname: 'Selena',
middlename: 'Marie'
};
var lastname = 'my last name';
var myWife = {
...myCrush,
lastname
}
console.log(myWife); // {firstname: 'Selena',
// middlename: 'Marie',
// lastname: 'my last name'}
There's another use for the three dots which is known as Rest Parameters and it makes it possible to take all of the arguments to a function in as one array.
Function arguments as array
function fun1(...params) {
}
... (three dots in JavaScript) is called the Spread Syntax or Spread Operator. This allows an iterable such as an array expression or string to be expanded or an object expression to be expanded wherever placed. This is not specific to React. It is a JavaScript operator.
All these answers here are helpful, but I want to list down the mostly used practical Use Cases of the Spread Syntax (Spread Operator).
1. Combine Arrays (Concatenate Arrays)
There are a variety of ways to combine arrays, but the spread operator allows you to place this at any place in an array. If you'd like to combine two arrays and place elements at any point within the array, you can do as follows:
var arr1 = ['two', 'three'];
var arr2 = ['one', ...arr1, 'four', 'five'];
// arr2 = ["one", "two", "three", "four", "five"]
2. Copying Arrays
When we wanted a copy of an array, we used to have the Array.prototype.slice() method. But, you can do the same with the spread operator.
var arr = [1,2,3];
var arr2 = [...arr];
// arr2 = [1,2,3]
3. Calling Functions without Apply
In ES5, to pass an array of two numbers to the doStuff() function, you often use the Function.prototype.apply() method as follows:
function doStuff (x, y, z) {}
var args = [0, 1, 2];
// Call the function, passing args
doStuff.apply(null, args);
However, by using the spread operator, you can pass an array into the function.
doStuff(...args);
4. Destructuring Arrays
You can use destructuring and the rest operator together to extract the information into variables as you'd like them:
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }
5. Function Arguments as Rest Parameters
ES6 also has three dots (...) which indicates a rest parameter that collects all remaining arguments of a function into an array.
function f(a, b, ...args) {
console.log(args);
}
f(1, 2, 3, 4, 5); // [3, 4, 5]
6. Using Math Functions
Any function where spread is used as the argument can be used by functions that can accept any number of arguments.
let numbers = [9, 4, 7, 1];
Math.min(...numbers); // 1
7. Combining Two Objects
You can use the spread operator to combine two objects. This is an easy and cleaner way to do it.
var carType = {
model: 'Toyota',
yom: '1995'
};
var carFuel = 'Petrol';
var carData = {
...carType,
carFuel
}
console.log(carData);
// {
// model: 'Toyota',
// yom: '1995',
// carFuel = 'Petrol'
// }
8. Separate a String into Separate Characters
You can use the spread operator to spread a string into separate characters.
let chars = ['A', ...'BC', 'D'];
console.log(chars); // ["A", "B", "C", "D"]
You can think of more ways to use the Spread Operator. What I have listed here are the popular use cases of it.
The three dots in JavaScript are the spread / rest operator.
Spread operator
The spread syntax allows an expression to be expanded in places where multiple arguments are expected.
myFunction(...iterableObj);
[...iterableObj, 4, 5, 6]
[...Array(10)]
Rest parameters
The rest parameter syntax is used for functions with a variable number of arguments.
function(a, b, ...theArgs) {
// ...
}
The spread / rest operator for arrays was introduced in ES6. There's a State 2 proposal for object spread / rest properties.
TypeScript also supports the spread syntax and can transpile that into older versions of ECMAScript with minor issues.
This is a feature of ES6, which is used in React as well. Look at the below example:
function Sum(x, y, z) {
return x + y + z;
}
console.log(Sum(1, 2, 3)); // 6
This way is fine if we have a maximum of three parameters. But, what if we need to add, for example, 110 parameters. Should we define them all and add them one by one?
Of course there is an easier way to do, which is called spread.
Instead of passing all those parameters you write:
function (...numbers){}
We have no idea how many parameters we have, but we know there are heaps of those.
Based on ES6, we can rewrite the above function as below and use the spread and mapping between them to make it as easy as a piece of cake:
let Sum = (...numbers) => {
return numbers.reduce((prev, current) => prev + current);
}
console.log(Sum(1, 2, 3, 4, 5, 6, 7, 8, 9)); // 45
Kudos to Brandon Morelli. He explained perfectly here, but links may die so I am just pasting the content below:
The spread syntax is simply three dots: ...
It allows an iterable to expand in places where 0+ arguments are expected.
Definitions are tough without context. Let's explore some different use cases to help understand what this means.
Example 1 — Inserting Arrays
Take a look at the code below. In this code, we don’t use the spread syntax:
var mid = [3, 4];
var arr = [1, 2, mid, 5, 6];
console.log(arr);
Above, we’ve created an array named mid. We then create a second array which contains our mid array. Finally, we log out the result. What do you expect arr to print? Click run above to see what happens. Here is the output:
[1, 2, [3, 4], 5, 6]
Is that the result you expected?
By inserting the mid array into the arr array, we’ve ended up with an array within an array. That’s fine if that was the goal. But what if you want only a single array with the values of 1 through 6? To accomplish this, we can use the spread syntax! Remember, the spread syntax allows the elements of our array to expand.
Let’s look at the code below. Everything is the same — except we’re now using the spread syntax to insert the mid array into the arr array:
var mid = [3, 4];
var arr = [1, 2, ...mid, 5, 6];
console.log(arr);
And when you hit the run button, here’s the result:
[1, 2, 3, 4, 5, 6]
Awesome!
Remember the spread syntax definition you just read above? Here’s where it comes into play. As you can see, when we create the arr array and use the spread operator on the mid array, instead of just being inserted, the mid array expands. This expansion means that each and every element in the mid array is inserted into the arr array. Instead of nested arrays, the result is a single array of numbers ranging from 1 to 6.
Example 2 — Math
JavaScript has a built-in math object that allows us to do some fun math calculations. In this example we’ll be looking at Math.max(). If you’re unfamiliar, Math.max() returns the largest of zero or more numbers. Here are a few examples:
Math.max();
// -Infinity
Math.max(1, 2, 3);
// 3
Math.max(100, 3, 4);
// 100
As you can see, if you want to find the maximum value of multiple numbers, Math.max() requires multiple parameters. You unfortunately can’t simply use a single array as input. Before the spread syntax, the easiest way to use Math.max() on an array is to use .apply().
var arr = [2, 4, 8, 6, 0];
function max(arr) {
return Math.max.apply(null, arr);
}
console.log(max(arr));
It works, it’s just really annoying.
Now take a look at how we do the same exact thing with the spread syntax:
var arr = [2, 4, 8, 6, 0];
var max = Math.max(...arr);
console.log(max);
Instead of having to create a function and utilize the apply method to return the result of Math.max() , we only need two lines of code! The spread syntax expands our array elements and inputs each element in our array individually into the Math.max() method!
Example 3 — Copy an Array
In JavaScript, you can’t just copy an array by setting a new variable equal to already existing array. Consider the following code example:
var arr = ['a', 'b', 'c'];
var arr2 = arr;
console.log(arr2);
When you press run, you’ll get the following output:
['a', 'b', 'c']
Now, at first glance, it looks like it worked — it looks like we’ve copied the values of arr into arr2. But that’s not what has happened. You see, when working with objects in JavaScript (arrays are a type of object) we assign by reference, not by value. This means that arr2 has been assigned to the same reference as arr. In other words, anything we do to arr2 will also affect the original arr array (and vice versa). Take a look below:
var arr = ['a', 'b', 'c'];
var arr2 = arr;
arr2.push('d');
console.log(arr);
Above, we’ve pushed a new element d into arr2. Yet, when we log out the value of arr, you’ll see that the d value was also added to that array:
['a', 'b', 'c', 'd']
No need to fear though! We can use the spread operator!
Consider the code below. It’s almost the same as above. Instead though, we’ve used the spread operator within a pair of square brackets:
var arr = ['a', 'b', 'c'];
var arr2 = [...arr];
console.log(arr2);
Hit run, and you’ll see the expected output:
['a', 'b', 'c']
Above, the array values in arr expanded to become individual elements which were then assigned to arr2. We can now change the arr2 array as much as we’d like with no consequences on the original arr array:
var arr = ['a', 'b', 'c'];
var arr2 = [...arr];
arr2.push('d');
console.log(arr);
Again, the reason this works is because the value of arr is expanded to fill the brackets of our arr2 array definition. Thus, we are setting arr2 to equal the individual values of arr instead of the reference to arr like we did in the first example.
Bonus Example — String to Array
As a fun final example, you can use the spread syntax to convert a string into an array. Simply use the spread syntax within a pair of square brackets:
var str = "hello";
var chars = [...str];
console.log(chars);
For someone who wants to understand this simple and fast:
First of all, this is not a syntax only to React. This is syntax from ES6 called spread syntax which iterate (merge, add, etc.) the array and object. Read more about it here.
So to answer the question:
Let's imagine you have this tag:
<UserTag name="Supun" age="66" gender="male" />
And you do this:
const user = {
"name": "Joe",
"age": "50"
"test": "test-val"
};
<UserTag name="Supun" gender="male" {...user} age="66" />
Then the tag will be equal to this:
<UserTag name="Joe" gender="male" test="test-val" age="66" />
So when you used the spread syntax in a React tag, it took the tag's attribute as object attributes which merge (replace if it exists) with the given object user. Also, you might have noticed one thing that it only replaces before attribute, not after attributes. So in this example, age remains as it is.
It's just defining props in a different way in JSX for you!
It's using ... array and object operator in ES6 (object one not fully supported yet), so basically if you already define your props, you can pass it to your element this way.
So in your case, the code should be something like this:
function yourA() {
const props = {name='Alireza', age='35'};
<Modal {...props} title='Modal heading' animation={false} />
}
so the props you defined, now separated and can be reused if necessary.
It's equal to:
function yourA() {
<Modal name='Alireza' age='35' title='Modal heading' animation={false} />
}
These are the quotes from React team about spread operator in JSX:
JSX Spread Attributes
If you know all the properties that you want to place on a component
ahead of time, it is easy to use JSX:
var component = <Component foo={x} bar={y} />;
Mutating Props is Bad If you don't know which properties you want to set, you might be tempted to add them onto the object later:
var component = <Component />;
component.props.foo = x; // bad
component.props.bar = y; // also bad
This is an anti-pattern because it means that we can't help you check
the right propTypes until way later. This means that your propTypes
errors end up with a cryptic stack trace.
The props should be considered immutable. Mutating the props object
somewhere else could cause unexpected consequences so ideally it would
be a frozen object at this point.
Spread Attributes Now you can use a new feature of JSX called spread attributes:
var props = {};
props.foo = x;
props.bar = y;
var component = <Component {...props} />;
The properties of the object that you pass in are copied onto the
component's props.
You can use this multiple times or combine it with other attributes.
The specification order is important. Later attributes override
previous ones.
var props = { foo: 'default' };
var component = <Component {...props} foo={'override'} />;
console.log(component.props.foo); // 'override'
What's with the weird ... notation? The ... operator (or spread operator) is already supported for arrays in ES6. There is also
an ECMAScript proposal for Object Rest and Spread Properties. We're
taking advantage of these supported and developing standards in order
to provide a cleaner syntax in JSX.
For those who come from the Python world, JSX Spread Attributes are equivalent to
Unpacking Argument Lists (the Python **-operator).
I'm aware this is a JSX question, but working with analogies sometimes helps to get it faster.
Three dots ... represent spread operators or rest parameters.
It allows an array expression or string or anything which can be iterating to be expanded in places where zero or more arguments for function calls or elements for array are expected.
Merge two arrays
var arr1 = [1,2,3];
var arr2 = [4,5,6];
arr1 = [...arr1, ...arr2];
console.log(arr1); //[1, 2, 3, 4, 5, 6]
Copying array:
var arr = [1, 2, 3];
var arr2 = [...arr];
console.log(arr); //[1, 2, 3]
Note: Spread syntax effectively goes one level deep while copying an
array. Therefore, it may be unsuitable for copying multidimensional
arrays as the following example shows (it's the same with
Object.assign() and spread syntax).
Add values of one array to other at specific index e.g 3:
var arr1 = [4, 5]
var arr2 = [1, 2, 3, ...arr1, 6]
console.log(arr2); // [1, 2, 3, 4, 5, 6]
When calling a constructor with new:
var dateFields = [1970, 0, 1]; // 1 Jan 1970
var d = new Date(...dateFields);
console.log(d);
Spread in object literals:
var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };
var clonedObj = { ...obj1 };
console.log(clonedObj); // {foo: "bar", x: 42}
var mergedObj = { ...obj1, ...obj2 };
console.log(mergedObj); // {foo: "baz", x: 42, y: 13}
Note that the foo property of obj1 has been overwritten by the obj2 foo property.
As a rest parameter syntax which allows us to represent an indefinite number of arguments as an array:
function sum(...theArgs) {
return theArgs.reduce((previous, current) => {
return previous + current;
});
}
console.log(sum(1, 2, 3)); //6
console.log(sum(1, 2, 3, 4)); //10
Note: The spread syntax (other than in the case of spread properties) can be applied only to iterable objects:
So the following will throw an error:
var obj = {'key1': 'value1'};
var array = [...obj]; // TypeError: obj is not iterable
Reference1
Reference2
The ...(spread operator) is used in React to:
provide a neat way to pass props from parent to child components. E.g., given these props in a parent component,
this.props = {
username: "danM",
email: "dan#mail.com"
}
they could be passed in the following manner to the child,
<ChildComponent {...this.props} />
which is similar to this
<ChildComponent username={this.props.username} email={this.props.email} />
but way cleaner.
The three dots (...) are called the spread operator, and this is conceptually similar to the ES6 array spread operator, JSX
taking advantage of these supported and developing standards in order to provide a cleaner syntax in JSX
Spread properties in object initializers copies own enumerable
properties from a provided object onto the newly created object.
let n = { x, y, ...z };
n; // { x: 1, y: 2, a: 3, b: 4 }
References:
Spread Properties
JSX In Depth
It is common practice to pass props around in a React application. In doing this we able to apply state changes to the child component regardless of whether it is Pure or Impure (stateless or stateful). There are times when the best approach, when passing in props, is to pass in singular properties or an entire object of properties. With the support for arrays in ES6 we were given the "..." notation and with this we are now able to achieve passing an entire object to a child.
The typical process of passing props to a child is noted with this syntax:
var component = <Component foo={x} bar={y} />;
This is fine to use when the number of props is minimal but becomes unmanageable when the prop numbers get too much higher. A problem with this method occurs when you do not know the properties needed within a child component and the typical JavaScript method is to simple set those properties and bind to the object later. This causes issues with propType checking and cryptic stack trace errors that are not helpful and cause delays in debugging. The following is an example of this practice, and what not to do:
var component = <Component />;
component.props.foo = x; // bad
component.props.bar = y;
This same result can be achieved but with more appropriate success by doing this:
var props = {};
props.foo = x;
props.bar = y;
var component = Component(props); // Where did my JSX go?
But does not use JSX spread or JSX so to loop this back into the equation we can now do something like this:
var props = {};
props.foo = x;
props.bar = y;
var component = <Component {...props} />;
The properties included in "...props" are foo: x, bar: y. This can be combined with other attributes to override the properties of "...props" using this syntax:
var props = { foo: 'default' };
var component = <Component {...props} foo={'override'} />;
console.log(component.props.foo); // 'override'
In addition we can copy other property objects onto each other or combine them in this manner:
var oldObj = { foo: 'hello', bar: 'world' };
var newObj = { ...oldObj, foo: 'hi' };
console.log(newObj.foo); // 'hi';
console.log(newObj.bar); // 'world';
Or merge two different objects like this (this is not yet available in all react versions):
var ab = { ...a, ...b }; // merge(a, b)
Another way of explaining this, according to Facebook's react/docs site is:
If you already have "props" as an object, and you want to pass it in JSX, you can use "..." as a SPREAD operator to pass the whole props object. The following two examples are equivalent:
function App1() {
return <Greeting firstName="Ben" lastName="Hector" />;
}
function App2() {
const props = {firstName: 'Ben', lastName: 'Hector'};
return <Greeting {...props} />;
}
Spread attributes can be useful when you are building generic containers. However, they can also make your code messy by making it easy to pass a lot of irrelevant props to components that don't care about them. This syntax should be used sparingly.
It is called spreads syntax in JavaScript.
It use for destructuring an array or object in JavaScript.
Example:
const objA = { a: 1, b: 2, c: 3 }
const objB = { ...objA, d: 1 }
/* Result of objB will be { a: 1, b: 2, c: 3, d: 1 } */
console.log(objB)
const objC = { ....objA, a: 3 }
/* result of objC will be { a: 3, b: 2, c: 3, d: 1 } */
console.log(objC)
You can do it same result with Object.assign() function in JavaScript.
Reference: Spread syntax
The spread operator (triple operator) introduced in ECMAScript 6 (ES6). ECMAScript (ES6) is a wrapper of JavaScript.
The spread operator enumerable properties in props.
this.props =
{
firstName: 'Dan',
lastName: 'Abramov',
city: 'New York',
country: 'USA'
}
<Modal {...this.props} title='Modal heading' animation={false}>
{...this.props} = { firstName: 'Dan',
lastName: 'Abramov',
city: 'New York',
country: 'USA' }
But the main feature spread operator is used for a reference type.
For example,
let person= {
name: 'Alex',
age: 35
}
person1 = person;
person1.name = "Raheel";
console.log( person.name); // Output: Raheel
This is called a reference type. One object affects other objects, because they are shareable in memory. If you are getting a value independently means spread memory and both use the spread operator.
let person= {
name: 'Alex',
age: 35
}
person2 = {...person};
person2.name = "Shahzad";
console.log(person.name); // Output: Alex
... 3 dots represent the spread operator in JS.
Without a spread operator.
let a = ['one','one','two','two'];
let unq = [new Set(a)];
console.log(a);
console.log(unq);
Output:
(4) ['one', 'one', 'two', 'two']
[Set(2)]
With spread operator.
let a = ['one','one','two','two'];
let unq = [...new Set(a)];
console.log(a);
console.log(unq);
Output:
(4) ['one', 'one', 'two', 'two']
(2) ['one', 'two']
Spread operator! As most ppl have already answered the question elegantly, I wanted to suggest a quick list of ways to use the spread operator:
The ... spread operator is useful for many different routine tasks in JavaScript, including the following:
Copying an array
Concatenating or combining arrays
Using Math functions
Using an array as arguments
Adding an item to a list
Adding to state in React
Combining objects
Converting NodeList to an array
Check out the article for more details. How to use the Spread Operator. I recommend getting used to it. There are so many cool ways you can use spread operators.
Those 3 dots ... is not React terms. Those are JavaScript ES6 spread operators. Which helps to create a new array without disturbing the original one to perform a deep copy. This can be used for objects also.
const arr1 = [1, 2, 3, 4, 5]
const arr2 = arr1 // [1, 2, 3, 4, 5]
/*
This is an example of a shallow copy.
Where the value of arr1 is copied to arr2
But now if you apply any method to
arr2 will affect the arr1 also.
*/
/*
This is an example of a deep copy.
Here the values of arr1 get copied but they
both are disconnected. Meaning if you
apply any method to arr3 it will not
affect the arr1.
*/
const arr3 = [...arr1] // [1, 2, 3, 4, 5]
<Modal {...{ title: "modal heading", animation: false, ...props} />
Much cleaner.
Those are called spreads. Just as the name implies, it means it's putting whatever the value of it in those array or objects.
Such as:
let a = [1, 2, 3];
let b = [...a, 4, 5, 6];
console.log(b);
> [1, 2, 3, 4, 5, 6]
The spread syntax allows an data structures like array and object to destructure
them for either to extract a value from them or to add a value to them.
e.g
const obj={name:"ram",age:10} const {name}=obj
from above example we can say that we destructured the obj and extracted name from that object.
similarly,
const newObj={...obj,address:"Nepal"}
from this example we added a new property to that object.
This is similar in case of array too.
The Spread operator lets you expand an iterable like an object, string, or array into its elements while the Rest operator does the inverse by reducing a set of elements into one array.
I can use Array() to have an array with a fixed number of undefined entries. For example
Array(2); // [empty × 2]
But if I go and use the map method, say, on my new array, the entries are still undefined:
Array(2).map( () => "foo"); // [empty × 2]
If I copy the array then map does work:
[...Array(2)].map( () => "foo"); // ["foo", "foo"]
Why do I need a copy to use the array?
When you use Array(arrayLength) to create an array, you will have:
a new JavaScript array with its length property set to that number (Note: this implies an array of arrayLength empty slots, not slots with actual undefined values).
The array does not actually contain any values, not even undefined values - it simply has a length property.
When you spread an iterable object with a length property into an array, spread syntax accesses each index and sets the value at that index in the new array. For example:
const arr1 = [];
arr1.length = 4;
// arr1 does not actually have any index properties:
console.log('1' in arr1);
const arr2 = [...arr1];
console.log(arr2);
console.log('2' in arr2);
And .map only maps properties/values for which the property actually exists in the array you're mapping over.
Using the array constructor is confusing. I would suggest using Array.from instead, when creating arrays from scratch - you can pass it an object with a length property, as well as a mapping function:
const arr = Array.from(
{ length: 2 },
() => 'foo'
);
console.log(arr);
The reason is that the array element is unassigned. See here the first paragraph of the description. ... callback is invoked only for indexes of the array which have assigned values, including undefined.
Consider:
var array1 = Array(2);
array1[0] = undefined;
// pass a function to map
const map1 = array1.map(x => x * 2);
console.log(array1);
console.log(map1);
Outputs:
Array [undefined, undefined]
Array [NaN, undefined]
When the array is printed each of its elements are interrogated. The first has been assigned undefined the other is defaulted to undefined.
The mapping operation calls the mapping operation for the first element because it has been defined (through assignment). It does not call the mapping operation for the second argument, and simply passes out undefined.
As pointed out by #CertainPerformance, your array doesn't have any properties besides its length, you can verify that with this line: new Array(1).hasOwnProperty(0), which returns false.
Looking at 15.4.4.19 Array.prototype.map you can see, at 7.3, there's a check whether a key exists in the array.
1..6. [...]
7. Repeat,
while k < len
Let
Pk be ToString(k).
Let
kPresent be the result of calling the [[HasProperty]]
internal method of O with argument Pk.
If
kPresent is true, then
Let
kValue be the result of calling the [[Get]] internal
method of O with argument Pk.
Let
mappedValue be the result of calling the [[Call]] internal
method of callbackfn with T as the this
value and argument list containing kValue, k, and
O.
Call
the [[DefineOwnProperty]] internal method of A with
arguments Pk, Property Descriptor {[[Value]]: mappedValue,
[[Writable]]: true, [[Enumerable]]: true,
[[Configurable]]: true}, and false.
Increase
k by 1.
9. Return A.
As pointed out already, Array(2) will only create an array of two empty slots which cannot be mapped over.
As far as some and every are concerned, Array(2) is indeed an empty array:
Array(2).some(() => 1 > 0); //=> false
Array(2).every(() => 1 < 0); //=> true
However this array of empty slots can somehow be "iterated" on:
[].join(','); //=> ''
Array(2).join(','); //=> ','
JSON.stringify([]) //=> '[]'
JSON.stringify(Array(2)) //=> '[null,null]'
So we can take that knowledge to come up with interesting and somewhat ironic ways to use ES5 array functions on such "empty" arrays.
You've come up with that one yourself:
[...Array(2)].map(foo);
A variation of a suggestion from #charlietfl:
Array(2).fill().map(foo);
Personally I'd recommend this one:
Array.from(Array(2)).map(foo);
A bit old school:
Array.apply(null, Array(2)).map(foo);
This one is quite verbose:
Array(2).join(',').split(',').map(foo);
What does the ... do in this React (using JSX) code and what is it called?
<Modal {...this.props} title='Modal heading' animation={false}>
That's property spread notation. It was added in ES2018 (spread for arrays/iterables was earlier, ES2015), but it's been supported in React projects for a long time via transpilation (as "JSX spread attributes" even though you could do it elsewhere, too, not just attributes).
{...this.props} spreads out the "own" enumerable properties in props as discrete properties on the Modal element you're creating. For instance, if this.props contained a: 1 and b: 2, then
<Modal {...this.props} title='Modal heading' animation={false}>
would be the same as
<Modal a={this.props.a} b={this.props.b} title='Modal heading' animation={false}>
But it's dynamic, so whatever "own" properties are in props are included.
Since children is an "own" property in props, spread will include it. So if the component where this appears had child elements, they'll be passed on to Modal. Putting child elements between the opening tag and closing tags is just syntactic sugar — the good kind — for putting a children property in the opening tag. Example:
class Example extends React.Component {
render() {
const { className, children } = this.props;
return (
<div className={className}>
{children}
</div>
);
}
}
ReactDOM.render(
[
<Example className="first">
<span>Child in first</span>
</Example>,
<Example className="second" children={<span>Child in second</span>} />
],
document.getElementById("root")
);
.first {
color: green;
}
.second {
color: blue;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Spread notation is handy not only for that use case, but for creating a new object with most (or all) of the properties of an existing object — which comes up a lot when you're updating state, since you can't modify state directly:
this.setState(prevState => {
return {foo: {...prevState.foo, a: "updated"}};
});
That replaces this.state.foo with a new object with all the same properties as foo except the a property, which becomes "updated":
const obj = {
foo: {
a: 1,
b: 2,
c: 3
}
};
console.log("original", obj.foo);
// Creates a NEW object and assigns it to `obj.foo`
obj.foo = {...obj.foo, a: "updated"};
console.log("updated", obj.foo);
.as-console-wrapper {
max-height: 100% !important;
}
... are called spread attributes which, as the name represents, it allows an expression to be expanded.
var parts = ['two', 'three'];
var numbers = ['one', ...parts, 'four', 'five']; // ["one", "two", "three", "four", "five"]
And in this case (I'm going to simplify it).
// Just assume we have an object like this:
var person= {
name: 'Alex',
age: 35
}
This:
<Modal {...person} title='Modal heading' animation={false} />
is equal to
<Modal name={person.name} age={person.age} title='Modal heading' animation={false} />
So in short, it's a neat short-cut, we can say.
The three dots represent the spread operator in ES6. It allows us to do quite a few things in JavaScript:
Concatenate arrays
var shooterGames = ['Call of Duty', 'Far Cry', 'Resident Evil'];
var racingGames = ['Need For Speed', 'Gran Turismo', 'Burnout'];
var games = [...shooterGames, ...racingGames];
console.log(games) // ['Call of Duty', 'Far Cry', 'Resident Evil', 'Need For Speed', 'Gran Turismo', 'Burnout']
Destructuring an array
var shooterGames = ['Call of Duty', 'Far Cry', 'Resident Evil'];
var [first, ...remaining] = shooterGames;
console.log(first); //Call of Duty
console.log(remaining); //['Far Cry', 'Resident Evil']
Combining two objects
var myCrush = {
firstname: 'Selena',
middlename: 'Marie'
};
var lastname = 'my last name';
var myWife = {
...myCrush,
lastname
}
console.log(myWife); // {firstname: 'Selena',
// middlename: 'Marie',
// lastname: 'my last name'}
There's another use for the three dots which is known as Rest Parameters and it makes it possible to take all of the arguments to a function in as one array.
Function arguments as array
function fun1(...params) {
}
... (three dots in JavaScript) is called the Spread Syntax or Spread Operator. This allows an iterable such as an array expression or string to be expanded or an object expression to be expanded wherever placed. This is not specific to React. It is a JavaScript operator.
All these answers here are helpful, but I want to list down the mostly used practical Use Cases of the Spread Syntax (Spread Operator).
1. Combine Arrays (Concatenate Arrays)
There are a variety of ways to combine arrays, but the spread operator allows you to place this at any place in an array. If you'd like to combine two arrays and place elements at any point within the array, you can do as follows:
var arr1 = ['two', 'three'];
var arr2 = ['one', ...arr1, 'four', 'five'];
// arr2 = ["one", "two", "three", "four", "five"]
2. Copying Arrays
When we wanted a copy of an array, we used to have the Array.prototype.slice() method. But, you can do the same with the spread operator.
var arr = [1,2,3];
var arr2 = [...arr];
// arr2 = [1,2,3]
3. Calling Functions without Apply
In ES5, to pass an array of two numbers to the doStuff() function, you often use the Function.prototype.apply() method as follows:
function doStuff (x, y, z) {}
var args = [0, 1, 2];
// Call the function, passing args
doStuff.apply(null, args);
However, by using the spread operator, you can pass an array into the function.
doStuff(...args);
4. Destructuring Arrays
You can use destructuring and the rest operator together to extract the information into variables as you'd like them:
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }
5. Function Arguments as Rest Parameters
ES6 also has three dots (...) which indicates a rest parameter that collects all remaining arguments of a function into an array.
function f(a, b, ...args) {
console.log(args);
}
f(1, 2, 3, 4, 5); // [3, 4, 5]
6. Using Math Functions
Any function where spread is used as the argument can be used by functions that can accept any number of arguments.
let numbers = [9, 4, 7, 1];
Math.min(...numbers); // 1
7. Combining Two Objects
You can use the spread operator to combine two objects. This is an easy and cleaner way to do it.
var carType = {
model: 'Toyota',
yom: '1995'
};
var carFuel = 'Petrol';
var carData = {
...carType,
carFuel
}
console.log(carData);
// {
// model: 'Toyota',
// yom: '1995',
// carFuel = 'Petrol'
// }
8. Separate a String into Separate Characters
You can use the spread operator to spread a string into separate characters.
let chars = ['A', ...'BC', 'D'];
console.log(chars); // ["A", "B", "C", "D"]
You can think of more ways to use the Spread Operator. What I have listed here are the popular use cases of it.
The three dots in JavaScript are the spread / rest operator.
Spread operator
The spread syntax allows an expression to be expanded in places where multiple arguments are expected.
myFunction(...iterableObj);
[...iterableObj, 4, 5, 6]
[...Array(10)]
Rest parameters
The rest parameter syntax is used for functions with a variable number of arguments.
function(a, b, ...theArgs) {
// ...
}
The spread / rest operator for arrays was introduced in ES6. There's a State 2 proposal for object spread / rest properties.
TypeScript also supports the spread syntax and can transpile that into older versions of ECMAScript with minor issues.
This is a feature of ES6, which is used in React as well. Look at the below example:
function Sum(x, y, z) {
return x + y + z;
}
console.log(Sum(1, 2, 3)); // 6
This way is fine if we have a maximum of three parameters. But, what if we need to add, for example, 110 parameters. Should we define them all and add them one by one?
Of course there is an easier way to do, which is called spread.
Instead of passing all those parameters you write:
function (...numbers){}
We have no idea how many parameters we have, but we know there are heaps of those.
Based on ES6, we can rewrite the above function as below and use the spread and mapping between them to make it as easy as a piece of cake:
let Sum = (...numbers) => {
return numbers.reduce((prev, current) => prev + current);
}
console.log(Sum(1, 2, 3, 4, 5, 6, 7, 8, 9)); // 45
Kudos to Brandon Morelli. He explained perfectly here, but links may die so I am just pasting the content below:
The spread syntax is simply three dots: ...
It allows an iterable to expand in places where 0+ arguments are expected.
Definitions are tough without context. Let's explore some different use cases to help understand what this means.
Example 1 — Inserting Arrays
Take a look at the code below. In this code, we don’t use the spread syntax:
var mid = [3, 4];
var arr = [1, 2, mid, 5, 6];
console.log(arr);
Above, we’ve created an array named mid. We then create a second array which contains our mid array. Finally, we log out the result. What do you expect arr to print? Click run above to see what happens. Here is the output:
[1, 2, [3, 4], 5, 6]
Is that the result you expected?
By inserting the mid array into the arr array, we’ve ended up with an array within an array. That’s fine if that was the goal. But what if you want only a single array with the values of 1 through 6? To accomplish this, we can use the spread syntax! Remember, the spread syntax allows the elements of our array to expand.
Let’s look at the code below. Everything is the same — except we’re now using the spread syntax to insert the mid array into the arr array:
var mid = [3, 4];
var arr = [1, 2, ...mid, 5, 6];
console.log(arr);
And when you hit the run button, here’s the result:
[1, 2, 3, 4, 5, 6]
Awesome!
Remember the spread syntax definition you just read above? Here’s where it comes into play. As you can see, when we create the arr array and use the spread operator on the mid array, instead of just being inserted, the mid array expands. This expansion means that each and every element in the mid array is inserted into the arr array. Instead of nested arrays, the result is a single array of numbers ranging from 1 to 6.
Example 2 — Math
JavaScript has a built-in math object that allows us to do some fun math calculations. In this example we’ll be looking at Math.max(). If you’re unfamiliar, Math.max() returns the largest of zero or more numbers. Here are a few examples:
Math.max();
// -Infinity
Math.max(1, 2, 3);
// 3
Math.max(100, 3, 4);
// 100
As you can see, if you want to find the maximum value of multiple numbers, Math.max() requires multiple parameters. You unfortunately can’t simply use a single array as input. Before the spread syntax, the easiest way to use Math.max() on an array is to use .apply().
var arr = [2, 4, 8, 6, 0];
function max(arr) {
return Math.max.apply(null, arr);
}
console.log(max(arr));
It works, it’s just really annoying.
Now take a look at how we do the same exact thing with the spread syntax:
var arr = [2, 4, 8, 6, 0];
var max = Math.max(...arr);
console.log(max);
Instead of having to create a function and utilize the apply method to return the result of Math.max() , we only need two lines of code! The spread syntax expands our array elements and inputs each element in our array individually into the Math.max() method!
Example 3 — Copy an Array
In JavaScript, you can’t just copy an array by setting a new variable equal to already existing array. Consider the following code example:
var arr = ['a', 'b', 'c'];
var arr2 = arr;
console.log(arr2);
When you press run, you’ll get the following output:
['a', 'b', 'c']
Now, at first glance, it looks like it worked — it looks like we’ve copied the values of arr into arr2. But that’s not what has happened. You see, when working with objects in JavaScript (arrays are a type of object) we assign by reference, not by value. This means that arr2 has been assigned to the same reference as arr. In other words, anything we do to arr2 will also affect the original arr array (and vice versa). Take a look below:
var arr = ['a', 'b', 'c'];
var arr2 = arr;
arr2.push('d');
console.log(arr);
Above, we’ve pushed a new element d into arr2. Yet, when we log out the value of arr, you’ll see that the d value was also added to that array:
['a', 'b', 'c', 'd']
No need to fear though! We can use the spread operator!
Consider the code below. It’s almost the same as above. Instead though, we’ve used the spread operator within a pair of square brackets:
var arr = ['a', 'b', 'c'];
var arr2 = [...arr];
console.log(arr2);
Hit run, and you’ll see the expected output:
['a', 'b', 'c']
Above, the array values in arr expanded to become individual elements which were then assigned to arr2. We can now change the arr2 array as much as we’d like with no consequences on the original arr array:
var arr = ['a', 'b', 'c'];
var arr2 = [...arr];
arr2.push('d');
console.log(arr);
Again, the reason this works is because the value of arr is expanded to fill the brackets of our arr2 array definition. Thus, we are setting arr2 to equal the individual values of arr instead of the reference to arr like we did in the first example.
Bonus Example — String to Array
As a fun final example, you can use the spread syntax to convert a string into an array. Simply use the spread syntax within a pair of square brackets:
var str = "hello";
var chars = [...str];
console.log(chars);
For someone who wants to understand this simple and fast:
First of all, this is not a syntax only to React. This is syntax from ES6 called spread syntax which iterate (merge, add, etc.) the array and object. Read more about it here.
So to answer the question:
Let's imagine you have this tag:
<UserTag name="Supun" age="66" gender="male" />
And you do this:
const user = {
"name": "Joe",
"age": "50"
"test": "test-val"
};
<UserTag name="Supun" gender="male" {...user} age="66" />
Then the tag will be equal to this:
<UserTag name="Joe" gender="male" test="test-val" age="66" />
So when you used the spread syntax in a React tag, it took the tag's attribute as object attributes which merge (replace if it exists) with the given object user. Also, you might have noticed one thing that it only replaces before attribute, not after attributes. So in this example, age remains as it is.
It's just defining props in a different way in JSX for you!
It's using ... array and object operator in ES6 (object one not fully supported yet), so basically if you already define your props, you can pass it to your element this way.
So in your case, the code should be something like this:
function yourA() {
const props = {name='Alireza', age='35'};
<Modal {...props} title='Modal heading' animation={false} />
}
so the props you defined, now separated and can be reused if necessary.
It's equal to:
function yourA() {
<Modal name='Alireza' age='35' title='Modal heading' animation={false} />
}
These are the quotes from React team about spread operator in JSX:
JSX Spread Attributes
If you know all the properties that you want to place on a component
ahead of time, it is easy to use JSX:
var component = <Component foo={x} bar={y} />;
Mutating Props is Bad If you don't know which properties you want to set, you might be tempted to add them onto the object later:
var component = <Component />;
component.props.foo = x; // bad
component.props.bar = y; // also bad
This is an anti-pattern because it means that we can't help you check
the right propTypes until way later. This means that your propTypes
errors end up with a cryptic stack trace.
The props should be considered immutable. Mutating the props object
somewhere else could cause unexpected consequences so ideally it would
be a frozen object at this point.
Spread Attributes Now you can use a new feature of JSX called spread attributes:
var props = {};
props.foo = x;
props.bar = y;
var component = <Component {...props} />;
The properties of the object that you pass in are copied onto the
component's props.
You can use this multiple times or combine it with other attributes.
The specification order is important. Later attributes override
previous ones.
var props = { foo: 'default' };
var component = <Component {...props} foo={'override'} />;
console.log(component.props.foo); // 'override'
What's with the weird ... notation? The ... operator (or spread operator) is already supported for arrays in ES6. There is also
an ECMAScript proposal for Object Rest and Spread Properties. We're
taking advantage of these supported and developing standards in order
to provide a cleaner syntax in JSX.
For those who come from the Python world, JSX Spread Attributes are equivalent to
Unpacking Argument Lists (the Python **-operator).
I'm aware this is a JSX question, but working with analogies sometimes helps to get it faster.
Three dots ... represent spread operators or rest parameters.
It allows an array expression or string or anything which can be iterating to be expanded in places where zero or more arguments for function calls or elements for array are expected.
Merge two arrays
var arr1 = [1,2,3];
var arr2 = [4,5,6];
arr1 = [...arr1, ...arr2];
console.log(arr1); //[1, 2, 3, 4, 5, 6]
Copying array:
var arr = [1, 2, 3];
var arr2 = [...arr];
console.log(arr); //[1, 2, 3]
Note: Spread syntax effectively goes one level deep while copying an
array. Therefore, it may be unsuitable for copying multidimensional
arrays as the following example shows (it's the same with
Object.assign() and spread syntax).
Add values of one array to other at specific index e.g 3:
var arr1 = [4, 5]
var arr2 = [1, 2, 3, ...arr1, 6]
console.log(arr2); // [1, 2, 3, 4, 5, 6]
When calling a constructor with new:
var dateFields = [1970, 0, 1]; // 1 Jan 1970
var d = new Date(...dateFields);
console.log(d);
Spread in object literals:
var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };
var clonedObj = { ...obj1 };
console.log(clonedObj); // {foo: "bar", x: 42}
var mergedObj = { ...obj1, ...obj2 };
console.log(mergedObj); // {foo: "baz", x: 42, y: 13}
Note that the foo property of obj1 has been overwritten by the obj2 foo property.
As a rest parameter syntax which allows us to represent an indefinite number of arguments as an array:
function sum(...theArgs) {
return theArgs.reduce((previous, current) => {
return previous + current;
});
}
console.log(sum(1, 2, 3)); //6
console.log(sum(1, 2, 3, 4)); //10
Note: The spread syntax (other than in the case of spread properties) can be applied only to iterable objects:
So the following will throw an error:
var obj = {'key1': 'value1'};
var array = [...obj]; // TypeError: obj is not iterable
Reference1
Reference2
The ...(spread operator) is used in React to:
provide a neat way to pass props from parent to child components. E.g., given these props in a parent component,
this.props = {
username: "danM",
email: "dan#mail.com"
}
they could be passed in the following manner to the child,
<ChildComponent {...this.props} />
which is similar to this
<ChildComponent username={this.props.username} email={this.props.email} />
but way cleaner.
The three dots (...) are called the spread operator, and this is conceptually similar to the ES6 array spread operator, JSX
taking advantage of these supported and developing standards in order to provide a cleaner syntax in JSX
Spread properties in object initializers copies own enumerable
properties from a provided object onto the newly created object.
let n = { x, y, ...z };
n; // { x: 1, y: 2, a: 3, b: 4 }
References:
Spread Properties
JSX In Depth
It is common practice to pass props around in a React application. In doing this we able to apply state changes to the child component regardless of whether it is Pure or Impure (stateless or stateful). There are times when the best approach, when passing in props, is to pass in singular properties or an entire object of properties. With the support for arrays in ES6 we were given the "..." notation and with this we are now able to achieve passing an entire object to a child.
The typical process of passing props to a child is noted with this syntax:
var component = <Component foo={x} bar={y} />;
This is fine to use when the number of props is minimal but becomes unmanageable when the prop numbers get too much higher. A problem with this method occurs when you do not know the properties needed within a child component and the typical JavaScript method is to simple set those properties and bind to the object later. This causes issues with propType checking and cryptic stack trace errors that are not helpful and cause delays in debugging. The following is an example of this practice, and what not to do:
var component = <Component />;
component.props.foo = x; // bad
component.props.bar = y;
This same result can be achieved but with more appropriate success by doing this:
var props = {};
props.foo = x;
props.bar = y;
var component = Component(props); // Where did my JSX go?
But does not use JSX spread or JSX so to loop this back into the equation we can now do something like this:
var props = {};
props.foo = x;
props.bar = y;
var component = <Component {...props} />;
The properties included in "...props" are foo: x, bar: y. This can be combined with other attributes to override the properties of "...props" using this syntax:
var props = { foo: 'default' };
var component = <Component {...props} foo={'override'} />;
console.log(component.props.foo); // 'override'
In addition we can copy other property objects onto each other or combine them in this manner:
var oldObj = { foo: 'hello', bar: 'world' };
var newObj = { ...oldObj, foo: 'hi' };
console.log(newObj.foo); // 'hi';
console.log(newObj.bar); // 'world';
Or merge two different objects like this (this is not yet available in all react versions):
var ab = { ...a, ...b }; // merge(a, b)
Another way of explaining this, according to Facebook's react/docs site is:
If you already have "props" as an object, and you want to pass it in JSX, you can use "..." as a SPREAD operator to pass the whole props object. The following two examples are equivalent:
function App1() {
return <Greeting firstName="Ben" lastName="Hector" />;
}
function App2() {
const props = {firstName: 'Ben', lastName: 'Hector'};
return <Greeting {...props} />;
}
Spread attributes can be useful when you are building generic containers. However, they can also make your code messy by making it easy to pass a lot of irrelevant props to components that don't care about them. This syntax should be used sparingly.
It is called spreads syntax in JavaScript.
It use for destructuring an array or object in JavaScript.
Example:
const objA = { a: 1, b: 2, c: 3 }
const objB = { ...objA, d: 1 }
/* Result of objB will be { a: 1, b: 2, c: 3, d: 1 } */
console.log(objB)
const objC = { ....objA, a: 3 }
/* result of objC will be { a: 3, b: 2, c: 3, d: 1 } */
console.log(objC)
You can do it same result with Object.assign() function in JavaScript.
Reference: Spread syntax
The spread operator (triple operator) introduced in ECMAScript 6 (ES6). ECMAScript (ES6) is a wrapper of JavaScript.
The spread operator enumerable properties in props.
this.props =
{
firstName: 'Dan',
lastName: 'Abramov',
city: 'New York',
country: 'USA'
}
<Modal {...this.props} title='Modal heading' animation={false}>
{...this.props} = { firstName: 'Dan',
lastName: 'Abramov',
city: 'New York',
country: 'USA' }
But the main feature spread operator is used for a reference type.
For example,
let person= {
name: 'Alex',
age: 35
}
person1 = person;
person1.name = "Raheel";
console.log( person.name); // Output: Raheel
This is called a reference type. One object affects other objects, because they are shareable in memory. If you are getting a value independently means spread memory and both use the spread operator.
let person= {
name: 'Alex',
age: 35
}
person2 = {...person};
person2.name = "Shahzad";
console.log(person.name); // Output: Alex
... 3 dots represent the spread operator in JS.
Without a spread operator.
let a = ['one','one','two','two'];
let unq = [new Set(a)];
console.log(a);
console.log(unq);
Output:
(4) ['one', 'one', 'two', 'two']
[Set(2)]
With spread operator.
let a = ['one','one','two','two'];
let unq = [...new Set(a)];
console.log(a);
console.log(unq);
Output:
(4) ['one', 'one', 'two', 'two']
(2) ['one', 'two']
Spread operator! As most ppl have already answered the question elegantly, I wanted to suggest a quick list of ways to use the spread operator:
The ... spread operator is useful for many different routine tasks in JavaScript, including the following:
Copying an array
Concatenating or combining arrays
Using Math functions
Using an array as arguments
Adding an item to a list
Adding to state in React
Combining objects
Converting NodeList to an array
Check out the article for more details. How to use the Spread Operator. I recommend getting used to it. There are so many cool ways you can use spread operators.
Those 3 dots ... is not React terms. Those are JavaScript ES6 spread operators. Which helps to create a new array without disturbing the original one to perform a deep copy. This can be used for objects also.
const arr1 = [1, 2, 3, 4, 5]
const arr2 = arr1 // [1, 2, 3, 4, 5]
/*
This is an example of a shallow copy.
Where the value of arr1 is copied to arr2
But now if you apply any method to
arr2 will affect the arr1 also.
*/
/*
This is an example of a deep copy.
Here the values of arr1 get copied but they
both are disconnected. Meaning if you
apply any method to arr3 it will not
affect the arr1.
*/
const arr3 = [...arr1] // [1, 2, 3, 4, 5]
<Modal {...{ title: "modal heading", animation: false, ...props} />
Much cleaner.
Those are called spreads. Just as the name implies, it means it's putting whatever the value of it in those array or objects.
Such as:
let a = [1, 2, 3];
let b = [...a, 4, 5, 6];
console.log(b);
> [1, 2, 3, 4, 5, 6]
The spread syntax allows an data structures like array and object to destructure
them for either to extract a value from them or to add a value to them.
e.g
const obj={name:"ram",age:10} const {name}=obj
from above example we can say that we destructured the obj and extracted name from that object.
similarly,
const newObj={...obj,address:"Nepal"}
from this example we added a new property to that object.
This is similar in case of array too.
The Spread operator lets you expand an iterable like an object, string, or array into its elements while the Rest operator does the inverse by reducing a set of elements into one array.
I know what is a for... in loop (it iterates over the keys), but I have heard about for... of for the first time (it iterates over values).
I am confused about for... of loop.
var arr = [3, 5, 7];
arr.foo = "hello";
for (var i in arr) {
console.log(i); // logs "0", "1", "2", "foo"
}
for (var i of arr) {
console.log(i); // logs "3", "5", "7"
// it doesn't log "3", "5", "7", "hello"
}
I understand that for... of iterates over property values. Then why doesn't it log "3", "5", "7", "hello" instead of "3", "5", "7"?
Unlike for... in loop, which iterates over each key ("0", "1", "2", "foo") and also iterates over the foo key, the for... of does not iterate over the value of foo property, i.e., "hello". Why it is like that?
Here I console for... of loop. It should log "3", "5", "7","hello" but it logs "3", "5", "7". Why?
Example Link
for in loops over enumerable property names of an object.
for of (new in ES6) does use an object-specific iterator and loops over the values generated by that.
In your example, the array iterator does yield all the values in the array (ignoring non-index properties).
I found a complete answer at Iterators and Generators (Although it is for TypeScript, this is the same for JavaScript too)
Both for..of and for..in statements iterate over lists; the values
iterated on are different though, for..in returns a list of keys on
the object being iterated, whereas for..of returns a list of values
of the numeric properties of the object being iterated.
Here is an example that demonstrates this distinction:
let list = [4, 5, 6];
for (let i in list) {
console.log(i); // "0", "1", "2",
}
for (let i of list) {
console.log(i); // "4", "5", "6"
}
Another distinction is that for..in operates on any object; it serves
as a way to inspect properties on this object. for..of on the other
hand, is mainly interested in values of iterable objects. Built-in
objects like Map and Set implement Symbol.iterator property allowing
access to stored values.
let pets = new Set(["Cat", "Dog", "Hamster"]);
pets["species"] = "mammals";
for (let pet in pets) {
console.log(pet); // "species"
}
for (let pet of pets) {
console.log(pet); // "Cat", "Dog", "Hamster"
}
Difference for..in and for..of:
Both for..in and for..of are looping constructs which are used to iterate over data structures. The only difference between them is the entities
they iterate over:
for..in iterates over all enumerable property keys of an object
for..of iterates over the values of an iterable object. Examples of iterable objects are arrays, strings, and NodeLists.
Example:
let arr = ['el1', 'el2', 'el3'];
arr.addedProp = 'arrProp';
// elKey are the property keys
for (let elKey in arr) {
console.log(elKey);
}
// elValue are the property values
for (let elValue of arr) {
console.log(elValue)
}
In this example we can observe that the for..in loop iterates over the keys of the object, which is an array object in this example. The keys are 0, 1, 2 (which correspond to the array elements) and addedProp. This is how the arr array object looks in chrome devtools:
You see that our for..in loop does nothing more than simply iterating over these keys.
The for..of loop in our example iterates over the values of a data structure. The values in this specific example are 'el1', 'el2', 'el3'. The values which an iterable data structure will return using for..of is dependent on the type of iterable object. For example an array will return the values of all the array elements whereas a string returns every individual character of the string.
For...in loop
The for...in loop improves upon the weaknesses of the for loop by eliminating the counting logic and exit condition.
Example:
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (const index in digits) {
console.log(digits[index]);
}
But, you still have to deal with the issue of using an index to access the values of the array, and that stinks; it almost makes it more confusing than before.
Also, the for...in loop can get you into big trouble when you need to add an extra method to an array (or another object). Because for...in loops loop over all enumerable properties, this means if you add any additional properties to the array's prototype, then those properties will also appear in the loop.
Array.prototype.decimalfy = function() {
for (let i = 0; i < this.length; i++) {
this[i] = this[i].toFixed(2);
}
};
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (const index in digits) {
console.log(digits[index]);
}
Prints:
0
1
2
3
4
5
6
7
8
9
function() {
for (let i = 0; i < this.length; i++) {
this[i] = this[i].toFixed(2);
}
}
This is why for...in loops are discouraged when looping over arrays.
NOTE: The forEach loop is another type of for loop in JavaScript.
However, forEach() is actually an array method, so it can only be used
exclusively with arrays. There is also no way to stop or break a
forEach loop. If you need that type of behavior in your loop, you’ll
have to use a basic for loop.
For...of loop
The for...of loop is used to loop over any type of data that is iterable.
Example:
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (const digit of digits) {
console.log(digit);
}
Prints:
0
1
2
3
4
5
6
7
8
9
This makes the for...of loop the most concise version of all the for loops.
But wait, there’s more! The for...of loop also has some additional benefits that fix the weaknesses of the for and for...in loops.
You can stop or break a for...of loop at anytime.
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (const digit of digits) {
if (digit % 2 === 0) {
continue;
}
console.log(digit);
}
Prints:
1
3
5
7
9
And you don’t have to worry about adding new properties to objects. The for...of loop will only loop over the values in the object.
Here is a useful mnemonic for remembering the difference between for...in Loop and for...of Loop.
"index in, object of"
for...in Loop => iterates over the index in the array.
for...of Loop => iterates over the object of objects.
for of is used to iterate over iterables and for in is used to iterate over object properties
Here's a trick to remember:
for of is not for objects (so it's for iterables)
for in is not for iterables (so it's for objects)
Another trick:
for in returns object indices (keys) while for of returns values
//for in, iterates keys in an object and indexes in an array
let obj={a:1, b:2}
for( const key in obj)
console.log(obj[key]); //would print 1 and 2
console.log(key); //would print a and b
let arr = [10, 11, 12, 13];
for (const item in arr)
console.log(item); //would print 0 1 2 3
//for of, iterates values in an array or any iterable
let arr = [10, 11, 12, 13];
for (const item of arr )
console.log(item); //would print 10 11 12 13
Another difference between the two loops, which nobody has mentioned before:
Destructuring for...in is deprecated. Use for...of instead.
Source
So if we want to use destructuring in a loop, for get both index and value of each array element, we should to use the for...of loop with the Array method entries():
for (const [idx, el] of arr.entries()) {
console.log( idx + ': ' + el );
}
The for...in statement iterates over the enumerable properties of an object, in an arbitrary order.
Enumerable properties are those properties whose internal [[Enumerable]] flag is set to true, hence if there is any enumerable property in the prototype chain, the for...in loop will iterate on those as well.
The for...of statement iterates over data that iterable object defines to be iterated over.
Example:
Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};
let iterable = [3, 5, 7];
for (let i in iterable) {
console.log(i); // logs: 0, 1, 2, "arrCustom", "objCustom"
}
for (let i in iterable) {
if (iterable.hasOwnProperty(i)) {
console.log(i); // logs: 0, 1, 2,
}
}
for (let i of iterable) {
console.log(i); // logs: 3, 5, 7
}
Like earlier, you can skip adding hasOwnProperty in for...of loops.
Short answer: for...in loops over keys, while for...of loops over values.
for (let x in ['a', 'b', 'c', 'd'] {
console.log(x);
}
// Output
0
1
2
3
for (let x of ['a', 'b', 'c', 'd'] {
console.log(x);
}
// Output
a
b
c
d
The for-in statement iterates over the enumerable properties of an object, in arbitrary order.
The loop will iterate over all enumerable properties of the object itself and those the object inherits from its constructor's prototype
You can think of it as "for in" basically iterates and list out all the keys.
var str = 'abc';
var arrForOf = [];
var arrForIn = [];
for(value of str){
arrForOf.push(value);
}
for(value in str){
arrForIn.push(value);
}
console.log(arrForOf);
// ["a", "b", "c"]
console.log(arrForIn);
// ["0", "1", "2", "formatUnicorn", "truncate", "splitOnLast", "contains"]
There are some already defined data types which allows us to iterate over them easily e.g Array, Map, String Objects
Normal for in iterates over the iterator and in response provides us with the keys that are in the order of insertion as shown in below example.
const numbers = [1,2,3,4,5];
for(let number in number) {
console.log(number);
}
// result: 0, 1, 2, 3, 4
Now if we try same with for of, then in response it provides us with the values not the keys. e.g
const numbers = [1,2,3,4,5];
for(let numbers of numbers) {
console.log(number);
}
// result: 1, 2, 3, 4, 5
So looking at both of the iterators we can easily differentiate the difference between both of them.
Note:- For of only works with the Symbol.iterator
So if we try to iterate over normal object, then it will give us an error e.g-
const Room = {
area: 1000,
height: 7,
floor: 2
}
for(let prop in Room) {
console.log(prop);
}
// Result area, height, floor
for(let prop of Room) {
console.log(prop);
}
Room is not iterable
Now for iterating over we need to define an ES6 Symbol.iterator e.g
const Room= {
area: 1000, height: 7, floor: 2,
[Symbol.iterator]: function* (){
yield this.area;
yield this.height;
yield this.floors;
}
}
for(let prop of Room) {
console.log(prop);
}
//Result 1000, 7, 2
This is the difference between For in and For of. Hope that it might clear the difference.
The for-in loop
for-in loop is used to traverse through enumerable properties of a collection, in an arbitrary order. A collection is a container type object whose items can be using an index or a key.
var myObject = {a: 1, b: 2, c: 3};
var myArray = [1, 2, 3];
var myString = "123";
console.log( myObject[ 'a' ], myArray[ 1 ], myString[ 2 ] );
for-in loop extracts the enumerable properties (keys) of a collection all at once and iterates over it one at a time. An enumerable property is the property of a collection that can appear in for-in loop.
By default, all properties of an Array and Object appear in for-in loop. However, we can use Object.defineProperty method to manually configure the properties of a collection.
var myObject = {a: 1, b: 2, c: 3};
var myArray = [1, 2, 3];
Object.defineProperty( myObject, 'd', { value: 4, enumerable: false } );
Object.defineProperty( myArray, 3, { value: 4, enumerable: false } );
for( var i in myObject ){ console.log( 'myObject:i =>', i ); }
for( var i in myArray ){ console.log( 'myArray:i =>', i ); }
In the above example, the property d of the myObject and the index 3 of myArray does not appear in for-in loop because they are configured with enumerable: false.
There are few issues with for-in loops. In the case of Arrays, for-in loop will also consider methods added on the array using myArray.someMethod = f syntax, however, myArray.length remains 4.
The for-of loop
It is a misconception that for-of loop iterate over the values of a collection. for-of loop iterates over an Iterable object. An iterable is an object that has the method with the name Symbol.iterator directly on it one on one of its prototypes.
Symbol.iterator method should return an Iterator. An iterator is an object which has a next method. This method when called return value and done properties.
When we iterate an iterable object using for-of loop, the Symbol.iterator the method will be called once get an iterator object. For every iteration of for-of loop, next method of this iterator object will be called until done returned by the next() call returns false. The value received by the for-of loop for every iteration if the value property returned by the next() call.
var myObject = { a: 1, b: 2, c: 3, d: 4 };
// make `myObject` iterable by adding `Symbol.iterator` function directlty on it
myObject[ Symbol.iterator ] = function(){
console.log( `LOG: called 'Symbol.iterator' method` );
var _myObject = this; // `this` points to `myObject`
// return an iterator object
return {
keys: Object.keys( _myObject ),
current: 0,
next: function() {
console.log( `LOG: called 'next' method: index ${ this.current }` );
if( this.current === this.keys.length ){
return { done: true, value: null }; // Here, `value` is ignored by `for-of` loop
} else {
return { done: false, value: _myObject[ this.keys[ this.current++ ] ] };
}
}
};
}
// use `for-of` loop on `myObject` iterable
for( let value of myObject ) {
console.log( 'myObject: value => ', value );
}
The for-of loop is new in ES6 and so are the Iterable and Iterables. The Array constructor type has Symbol.iterator method on its prototype. The Object constructor sadly doesn't have it but Object.keys(), Object.values() and Object.entries() methods return an iterable (you can use console.dir(obj) to check prototype methods). The benefit of the for-of loop is that any object can be made iterable, even your custom Dog and Animal classes.
The easy way to make an object iterable is by implementing ES6 Generator instead of custom iterator implementation.
Unlike for-in, for-of loop can wait for an async task to complete in each iteration. This is achieved using await keyword after for statement documentation.
Another great thing about for-of loop is that it has Unicode support. According to ES6 specifications, strings are stored with UTF-16 encoding. Hence, each character can take either 16-bit or 32-bit. Traditionally, strings were stored with UCS-2 encoding which has supports for characters that can be stored within 16 bits only.
Hence, String.length returns number of 16-bit blocks in a string. Modern characters like an Emoji character takes 32 bits. Hence, this character would return length of 2. for-in loop iterates over 16-bit blocks and returns the wrong index. However, for-of loop iterates over the individual character based on UTF-16 specifications.
var emoji = "😊🤣";
console.log( 'emoji.length', emoji.length );
for( var index in emoji ){ console.log( 'for-in: emoji.character', emoji[index] ); }
for( var character of emoji ){ console.log( 'for-of: emoji.character', character ); }
for...of loop works only with iterable objects. In JavaScript, iterables are objects which can be looped over.
String, Array, TypedArray, Map, and Set are all built-in iterables, because each of their prototype objects implements an ##iterator method. So, for...of loop works on the mentioned object types.
Object in JavaScript is not iterable by default. So, for...of loop does not work on objects.
In simple words, for...of works with strings and arrays but not with objects.
for...in works with those properties whose enumerable flag is set to true.
Enumerable flag for properties created via simple assignment or property initializer are by default true.
Enumerable flag for properties created via Object.defineProperty are by default false.
Here is a more detailed post with examples: https://dev.to/swastikyadav/difference-between-forof-and-forin-loop-in-javascript-j2o
A see a lot of good answers, but I decide to put my 5 cents just to have good example:
For in loop
iterates over all enumerable props
let nodes = document.documentElement.childNodes;
for (var key in nodes) {
console.log( key );
}
For of loop
iterates over all iterable values
let nodes = document.documentElement.childNodes;
for (var node of nodes) {
console.log( node.toString() );
}
When I first started out learning the for in and of loop, I was confused with my output too, but with a couple of research and understanding you can think of the individual loop like the following :
The
for...in loop returns the indexes of the individual property and has no effect of impact on the property's value, it loops and returns information on the property and not the value.
E.g
let profile = {
name : "Naphtali",
age : 24,
favCar : "Mustang",
favDrink : "Baileys"
}
The above code is just creating an object called profile, we'll use it for both our examples, so, don't be confused when you see the profile object on an example, just know it was created.
So now let us use the for...in loop below
for(let myIndex in profile){
console.log(`The index of my object property is ${myIndex}`)
}
// Outputs :
The index of my object property is 0
The index of my object property is 1
The index of my object property is 2
The index of my object property is 3
Now Reason for the output being that we have Four(4) properties in our profile object and indexing as we all know starts from 0...n, so, we get the index of properties 0,1,2,3 since we are working with the for..in loop.
for...of loop* can return either the property, value or both, Let's take a look at how.
In javaScript, we can't loop through objects normally as we would on arrays, so, there are a few elements we can use to access either of our choices from an object.
Object.keys(object-name-goes-here) >>> Returns the keys or properties of an object.
Object.values(object-name-goes-here) >>> Returns the values of an object.
Object.entries(object-name-goes-here) >>> Returns both the keys and values of an object.
Below are examples of their usage, pay attention to Object.entries() :
Step One: Convert the object to get either its key, value, or both.
Step Two: loop through.
// Getting the keys/property
Step One: let myKeys = ***Object.keys(profile)***
Step Two: for(let keys of myKeys){
console.log(`The key of my object property is ${keys}`)
}
// Getting the values of the property
Step One: let myValues = ***Object.values(profile)***
Step Two : for(let values of myValues){
console.log(`The value of my object property is ${values}`)
}
When using Object.entries() have it that you are calling two entries on the object, i.e the keys and values. You can call both by either of the entry. Example Below.
Step One: Convert the object to entries, using ***Object.entries(object-name)***
Step Two: **Destructure** the ***entries object which carries the keys and values***
like so **[keys, values]**, by so doing, you have access to either or both content.
// Getting the keys/property
Step One: let myKeysEntry = ***Object.entries(profile)***
Step Two: for(let [keys, values] of myKeysEntry){
console.log(`The key of my object property is ${keys}`)
}
// Getting the values of the property
Step One: let myValuesEntry = ***Object.entries(profile)***
Step Two : for(let [keys, values] of myValuesEntry){
console.log(`The value of my object property is ${values}`)
}
// Getting both keys and values
Step One: let myBothEntry = ***Object.entries(profile)***
Step Two : for(let [keys, values] of myBothEntry){
console.log(`The keys of my object is ${keys} and its value
is ${values}`)
}
Make comments on unclear parts section(s).
Everybody did explain why this problem occurs, but it's still very easy to forget about it and then scratching your head why you got wrong results. Especially when you're working on big sets of data when the results seem to be fine at first glance.
Using Object.entries you ensure to go trough all properties:
var arr = [3, 5, 7];
arr.foo = "hello";
for ( var [key, val] of Object.entries( arr ) ) {
console.log( val );
}
/* Result:
3
5
7
hello
*/
In simple terms forIN iterates over the KEYS IN the array(index)/object(key),
whereas forOF iterates over the VALUES OF the array(value).
I am trying to get my head around arrays in JS. My question is; are the following two tests equivalent?
var test = 2;
console.log(test in [1,2,3]);
console.log([1,2,3].indexOf(test) != -1);
They seem to be, but then answers like this and the book I am reading suggest that you can't do in on an array, only on an object. Looking for clarity. There must be a reason that people use .indexOf(x) (which I assume is linear time) and not in (which I assume is constant time).
No. They are completely different.
test in [1,2,3] checks if there is a property named 2 in the object. There is, it has the value 3.
[1,2,3].indexOf(test) gets the first property with the value 2 (which is in the property named 1)
suggest that you can't do in on an array, only on an object
Arrays are objects. (A subclass if we want to use classical OO terminally, which doesn't really fit for a prototypal language like JS, but it gets the point across).
The array [1, 2, 3] is like an object { "0": 1, "1": 2, "2": 3 } (but inherits a bunch of other properties from the Array constructor).
As per MDN,
The in operator returns true if the specified property is in the specified object.
in will check for keys. Its similar to Object.keys(array).indexOf(test)
var a1 = [1,2,3];
var a2 = ['a', 'b', 'c']
var test = 2;
console.log(test in a1)
console.log(test in a2)
// Ideal way
//ES5
console.log(a1.indexOf(test)>-1)
console.log(a2.indexOf(test)>-1)
//ES6
console.log(a1.includes(test))
console.log(a2.includes(test))
The first checks for an index, or if property of an object exists,
console.log(test in [1,2,3]);
and not for a value in the array, as the second is doing.
console.log([1,2,3].indexOf(test) != -1);
The in operator returns true if the specified property is in the
specified object.
Using in operator for an array checks of the indices and the length property - because those are the properties for an array:
console.log(Object.getOwnPropertyNames([1, 2, 3]));
console.log(Object.keys([1, 2, 3]));
console.log('length' in [1, 2, 3]);
Object.keys : return all enumerable properties
Object.getOwnPropertyNames : return all properties
Try this
var test = 2;
var arrval= [1, 5, 2, 4];
var a = arrval.indexOf(test);
if(a>-1) console.log("Having");
else console.log("Not Having");