What Is Spreadelement in Ecmascript Documentation? Is It the Same as Spread Syntax At Mdn

What is SpreadElement in ECMAScript documentation? Is it the same as Spread syntax at MDN?

The term "spread operator" is kind of an "umbrella term" that refers to various syntactic constructs in ES6 which all look like ...x. MDN does the same.

However, this is misguiding, because ... is not an operator (at least not in the sense the ECMAScript spec uses the term "operator"). It doesn't generate a value that can be used in further computations. I'd rather compare it to other punctuators, such as , or ; (which are also kind of related but have different meaning in different context).

The term "spread operator" could refer to:

  • Spread element, var arr = [a, b, ...c];: The spread element expands the iterable (c) into the new array. It's equivalent to something like [a,b].concat(c).

  • Rest element, [a, b, ...c] = arr;: Inside destructuring, the ... construct has the opposite effect: It collects remaining elements into an array. The example here is equivalent to

    a = arr[0];
    b = arr[1];
    c = arr.slice(2);

    (note that this only an approximation, because destructuring works on any iterable value, not just arrays)

  • fun(a, b, ...c): This construct doesn't actually have a name in the spec. But it works very similar as spread elements do: It expands an iterable into the list of arguments.

    It would be equivalent to func.apply(null, [a, b].concat(c)).

    The lack of an official name might be the reason why people started to use "spread operator". I would probably call it "spread argument".

  • Rest parameter: function foo(a, b, ...c): Similar like rest elements, the rest parameter collects the remaining arguments passed to the function and makes them available as array in c. The ES2015 actually spec uses the term BindingRestElement to refer to to this construct.

Related questions:

  • Spread operator vs Rest parameter in ES2015/es6
  • Using spread operator multiple times in javascript?

: If we are very pedantic we would even have to distinguish between a variable declaration (var [a, b, ...c] = d;) and simple assignment ([a, b, ...c] = d;), according to the spec.

Is it spread syntax or the spread operator ?

It's not an operator.

In all senses of the word, it's not one. It has been a huge misconception since it was introduced and despite popular opinion -- it's not one, and there are a few objective points to be made:

  • It doesn't fit the definition of an operator
  • It can't be used as an operator
  • The language specification implies that it's not an operator

It should be mentioned that spread syntax comes in different 'flavors', used in different contexts and are commonly referred to by different names while using the same punctuator. Spread syntax is basically an umbrella term for the application of the ... punctuator, and see Felix Kling's great answer detailing all the uses and names. More explanation about these individuals uses is given in the supplementary answer.

What is an operator?

Semantically, in the context of ECMAScript, operators are just builtin functions that take in arguments and evaluate to a single value -- written in prefix, infix, or postfix notation and usually with symbolic names such as + or /. From Wikipedia:

Simply, an expression involving an operator is evaluated in some way, and the resulting value may be just a value (an r-value), or may be an object allowing assignment (an l-value).

For example, the + operator results in a value such as 2, which is a right-hand-side expression, and the . operator results in an object allowing assignment such as foo.bar, a left-hand-side expression.

On the surface, the ... punctuator1 looks to be a prefix unary operator:

const baz = [foo, ...bar];

But the problem with that argument is that ...bar doesn't evaluate to a singular value; it spreads the iterable bar's elements, one by one. The same goes for spread arguments:

foo(...bar);

Here, foo receives separate arguments from the iterable bar. They're separate values being passed to foo, not just one value. It doesn't fit the definition of an operator, so it isn't one.

Why isn't it an operator?

Another point to be made is that operators are meant to be standalone and return a single value. For example:

const bar = [...foo];

As already mentioned, this works well. The problem arises when you try to do this:

const bar = ...foo;

If spread syntax were an operator, the latter would work fine because operators evaluate the expression to a single value but spread doesn't so it fails. Spread syntax and spread arguments only work in the context of arrays and function calls because those structures receive multiple values supplied by spreading array elements or arguments. Evaluating to multiple values is outside of the scope of what an operator is able to do.

What do the standards say?

The complete list of operators is listed in Clauses §12.5 through §12.15 in the ECMAScript 2015 Language Specification, the specification in which ... is introduced, which doesn't mention .... It can also be inferred that it's not an operator. The two main cases mentioned in this answer in which spread syntax is in a production, for function calls (spread arguments) or array literals (spread syntax) are described below:

ArrayLiteral :
[ Elisionopt ]
[ ElementList ]
[ ElementList , Elisionopt ]

ElementList :
Elisionopt AssignmentExpression
Elisionopt SpreadElement
ElementList , Elisionopt AssignmentExpression
ElementList , Elisionopt SpreadElement

Elision :
,
Elision ,

SpreadElement :
... AssignmentExpression

And for function calls:

CallExpression :
MemberExpression Arguments

Arguments :
( )
( ArgumentList )

ArgumentList :
AssignmentExpression
... AssignmentExpression
ArgumentList , AssignmentExpression
ArgumentList , ... AssignmentExpression

In these productions, there's a conclusion that can be made: that the spread 'operator' doesn't exist. As mentioned earlier, operators should be standalone, as in const bar = ...foo and evaluate to one single value. The syntax of the language prevents this, which means spread syntax was never meant to be standalone. It's an extension to array initializers and function calls, an extension to their grammar.

Why spread 'syntax'?

Syntax, as defined by Wikipedia:

In computer science, the syntax of a computer language is the set of rules that defines the combinations of symbols that are considered to be a correctly structured document or fragment in that language.

Syntax is basically the 'form' of the language, rules that govern what is legal or not regarding how the code should look, and how the code should be written. In this case, ECMAScript's grammar specifically defines the ... punctuator to only appear in function calls and array literals as an extension -- which is a rule that defines a combination of symbols (...foo) that are considered to be legal together, thus it is syntax similar to how an arrow function (=>) is not an operator, but syntax2.

Calling ... an operator is a misnomer. An operator is a builtin function that takes in arguments (operands) and is in the form of prefix, infix, or postfix notation and evaluates to exactly one value. ..., while satisfying the first two conditions, does not satisfy the last. ..., instead, is syntax because it is defined specifically and explicitly in the language's grammar. Thus, 'the spread operator' is objectively more correctly referred to as 'spread syntax'.


1 The term 'punctuator' refers to punctuators in ECMAScript 2015 and later specifications. These symbols include syntax components and operators, and are punctators of the language. ... is a punctuator itself, but the term 'spread syntax' refers to the whole application of the punctuator.

2 => itself is a punctuator, just as ... but what I'm referring to specifically is arrow function syntax, the application of the => punctuator ((…) => { … }), just as spread syntax refers to the application of the ... punctuator.

... operator in Javascript

I have a way of thinking which makes it very easy to understand and remember how '...' works.

var arr = [1,2,3] // this is arr which is the array

on the other hand

...arr            // this is whatever inside arr, which is 1,2,3

So you can also think of it as taking what is inside of an array.


Note that by its own, ...arr is not a valid syntax. You can use it in
many ways , two of them coming to my mind are :

1 - Pass what is inside an array to a function

var arr = [ 1,2,3 ]
var myFunc = function(a,b,c) {
console.log(a,b,c)
}
myFunc(..arr) // logs 1 2 3

myFunc(1,2,3) // logs 1 2 3

2 - Take what is inside of an array and use them in another array.

var arr = [ 1,2,3 ]
var foo = [ ...arr, 4,5,6 ] // now foo is [ 1,2,3,4,5,6 ]

How to use spread syntax or destructuring into `this` value?

You can't update this by spreading and then assigning the result.

You can use Object.assign() to copy properties from the obj to this:

class A {

constructor(obj) {

Object.assign(this, obj);

}

}

const a = { b: 1, c: 2 }

console.log(new A(a));

Why is a spread element unsuitable for copying multidimensional arrays?

Arrays are objects, and [...a] creates a shallow copy of a array object.

For the language itself there are no multidimentional arrays - there are another arrays inside an array. It doesn't matter if contains arrays, plain objects, functions or primitives. For primitives, their values will be copied. Otherwise, the references to objects will be copied. This is what

It's the same case with Object.assign() and Object spread operators

part refers to.

And regarding

The above code sample works just the same as if you'd copied the array in a to b using the .slice() method

...it truly does. This is a neater way to write a.slice() or [].concat(a). With a considerable exception. ES6 rest operator (as well as Array.from(a)) works equally for all iterables, not just for arrays.

For a deep copy of an object ES6 offers nothing new, an object (which an array is) should be recursively copied by hand. To address all the concerns it still makes sense to use proven third-party helper functions, such as Lodash cloneDeep.

JavaScript: Spread Syntax and Rest Parameters

Spread syntax and Rest Parameters

I strongly recommend taking a look at the documentation, as it is very comprehensive and informative.

Spread Syntax

Spread syntax allows an iterable such as an array expression to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.

Example:

const array1 = [0, 1, 2, 3];
const array2 = [...array1, 4, 5, 6];

// array2 = [0, 1, 2, 3, 4, 5, 6,]

// Iterates over all properties of the specified object, adding it to the new object
// let objClone = { ...obj };

Rest parameters

The rest parameter syntax allows us to represent an indefinite number of arguments as an array.

Example:

function fun1(...theArgs) {
console.log(theArgs.length);
}

fun1(); // 0
fun1(5); // 1
fun1(5, 6, 7); // 3

How to compare to spread argument?

The logic is wrong.

var arr = [1, 4, 10];

if(Math.min(...arr) <= 1) {
console.log('Must be greater than 1');
}

Spread operator for strings

As we can see below, your example is actually spreading to 5 elements, where 2 of them are space characters. You can also see below that the spread operator on a string seems to be the same as using .split('').

const x = "1 2 3";

console.log([...x]);

console.log(x.split(''));


Related Topics



Leave a reply



Submit