JavaScript's two main collection types are arrays and objects. Arrays are created with square brackets, for example const arr = [1, 'a', true]; or with the new Array() constructor, and they are zero-indexed collections that can hold values of any type. The mutating array methods follow a consistent pattern: push() adds to the end, pop() removes from the end, shift() removes from the start, and unshift() adds to the start. Objects are created with the object-literal syntax { key: value }, as in const obj = {name: 'JS'};, where keys are strings (or symbols) and values can be anything.
Object properties can be read or set with either dot notation, obj.prop, or bracket notation, obj['prop']. Bracket notation is required when the key is dynamic or stored in a variable. ES6 added a great deal of expressive syntax on top of these collections. Template literals, written with backticks, let you embed expressions directly into strings: `Hello ${name}` interpolates the value of name, and template literals also support multi-line strings and tagged templates. Destructuring assignment extracts values from arrays or objects into variables in a single step, such as const [a, b] = [1, 2]; or const {x} = {x: 10};.
The spread operator (...) expands an iterable into individual elements, which is handy for shallow copying arrays with const newArr = [...oldArr, 1]; or for passing many arguments to a function such as Math.max(...nums). The closely related rest parameter syntax also uses ... but in the opposite direction: in a function definition, function sum(...nums) {} collects all remaining arguments into a real array. Rest parameters must come last. Default parameters let you supply fallback values that are evaluated only when the argument is undefined, for example function greet(name = 'World') {}. Together, these features reduce boilerplate and make data manipulation concise.