Accessor methods read an array and return a new value, leaving the original untouched, so they are safe on data you do not own, such as component props or application state. Do not confuse slice() (copies a range) with splice() (a mutator, Mutator Methods).
| Method | Returns | Mutates? |
|---|---|---|
| concat(...items) | New array; arrays spread | No |
| slice(start?, end?) | Shallow copy of a range | No |
| includes(value) | Boolean; finds NaN | No |
| indexOf(), lastIndexOf() | Index or -1 | No |
| at(index) | Element; -1 is the last | No |
| join(sep), toString() | String of all elements | No |
const a = [3, 4].concat(5, [6, [7]]); // one level of arrays is spread
console.log(a, a.slice(1, 3), a.slice(-2));
console.log(a.join('-'), `{${a}}`); // template literal calls toString()
console.log([NaN].indexOf(NaN), [NaN].includes(NaN));
console.log([[1]].includes([1]), a.indexOf(5), a.at(-1)); // objects match by identity[ 3, 4, 5, 6, [ 7 ] ] [ 4, 5 ] [ 6, [ 7 ] ]
3-4-5-6-7 {3,4,5,6,7}
-1 true
false 2 [ 7 ]includes() (ES2016) uses SameValueZero, so unlike indexOf() and its === test it finds NaN. Both compare objects by reference; search by content with find() (Iteration Methods). slice() and concat() copy only the top level, so nested objects stay shared (Copying and Comparing). Interview favorite: [] + {} is '[object Object]' because + converts both operands to primitive strings.