JavaScript - Array
Tags: bfe, javascript, programming
Published: 2022-05-09 12:23:23

#### Array

<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array">Array - MDN</a>

In JavaScript, arrays aren't primitives but are instead Array objects with the following core characteristics:

- JavaScript arrays are <b>resizable</b> and <b>can contain a mix of different data types</b>.(If you want an array only contains one type of variables, use <i>typed arrays</i> instead. -- Int8Array, Uint8Array.etc.)

- JavaScript arrays are not associative arrays(key value pairs data structure like map), so it <b>must be accessed using integers as indexes</b>.

- JavaScript arrays start at 0 index

- JavaScript <b>array-copy operations create shallow copies</b>

<b>1. Array-copy operations</b>

- spread syntax

```js
const fruits = ["Strawberry", "Mango"];
const fruitsCopy = [...fruits];
```

- from( ) method

```js
const fruits = ["Strawberry", "Mango"];
const fruitsCopy = Array.from(fruits);
```

- slice( ) method

```js
const fruits = ["Strawberry", "Mango"];
const fruitsCopy = fruits.slice();
```

All the array-copy operations above are implemented by copying each element's value to the new array. When an array contains reference type elements, these operations will only copy the reference of these elements instead of saving the copies in a new memory space.

<b>2. Shallow copy & Deep copy</b>

- shallow copy
  A shallow copy of an object is a copy whose properties share the same references as those of the source object from which the copy was made. As a result, when you change either the source or the copy, you may also cause the other object to change too.

```js
let arr = [[1, 2, 3], 4, 5, 6];
let arrCopy = [...arr];
// or arr.from() or arr.slice()

arrCopy[0][2] = 4;
console.log(arr); // [[1, 2, 4], 4, 5, 6]
// original array has been modified. This is because the reference of arr[0] and arrCopy[0] is the same. So no matter which of them has been changed, the other one will also be changed.
```

<a href="https://stackoverflow.com/questions/24512712/what-is-the-difference-between-a-shallow-copy-and-a-deep-copy-with-javascript-ar">Shallow copy's problem</a>

- deep copy
  A deep copy of an object is a copy whose properties do not share the same references as those of the source object from which the copy was made. As a result, when you change either the source or the copy, you can be assured you're not causing the other object to change too. One way to make a deep copy of a JavaScript object is to use JSON.stringify() to convert the object to a JSON string, and then JSON.parse() to convert the string back into a completely new JavaScript object.

```js
const fruits = ["Strawberry", "Mango"];
const fruitsDeepCopy = JSON.parse(JSON.stringify(fruits));
```

<b>Array Methods</b>

- concat( )
  The `concat()` method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array.
  ```js
  let arr1 = [1, 2, 3];
  let arr2 = [4, 5, 6];
  let arr3 = arr1.concat(arr2);
  console.log(arr3); // [1,2,3,4,5,6]
  ```

* every( )
  The `every()` method tests whether all elements in the array pass the test implemented by the provided function. It returns a Boolean value.

  ```js
  function func(value) {
    return value < 4;
  }

  let arr = [1, 2, 3];
  console.log(arr.every(func)); //true
  ```

* fill( )
  The `fill()` method changes all elements in an array to a static value, from a start index(default `0`) to an end index(default `array.length`). It returns the mmodified array. Syntax:

   - `fill(value)`
     Value to fill the array with. (All elements in the array will be this exact value.)

   ```js
   let arr = [1, 2, 3];
   arr.fill(6);
   console.log(arr); //[6,6,6]
   ```

  - `fill(value, start)`
    Start index(inclusive), default `0`.

  ```js
  let arr = [1, 2, 3];
  arr.fill(6, 1);
  console.log(arr); //[1,6,6]
  ```

  - `fill(value, start, end)`
    End index(exclusive), default `arr.length`.

  ```js
  let arr = [1, 2, 3];
  arr.fill(6, 1, 2);
  console.log(arr); //[1,6,3]
  ```

* filter( )
  The `filter()` method <b>creates a new array</b> with all elements that pass the test implemented by the provided function.

  ```js
  function func(value) {
    return value <= 2;
  }

  let arr = [1, 2, 3];
  let filteredArr = arr.filter(func);
  console.log(filteredArr); //[1,2]
  ```

* find( )
  The `find()` method returns the first element in the provided array that satisfies the provided testing function. If no values satisfy the testing function, `undefined` is returned.

  ```js
  let arr = [1, 2, 3];
  const found = arr.find((element) => element > 2);
  console.log(found); // 3
  ```

* findIndex( )
  The `findIndex()` method returns the <b>index</b> of the first element in the array <b>that satisfies the provided testing function</b>. Otherwise, it returns `-1`, indicating that no element passed the test.
  ```js
  let arr = [1, 2, 3];
  const foundIndex = arr.findIndex((element) => element > 2);
  console.log(foundIndex); // 2
  ```
* flat( )
  The `flat()` method creates a new array with all sub-array elements concatenated into it recursively up to the specified depth.
  - `flat(depth)`
    The depth level specifying how deep a nested array structure should be flattend. Defaults to 1.
    ```js
    let arr = [1, 2, 3, [[4, 5]]];
    console.log(arr.flat()); // depth = 1, [1,2,3,[4,5]]
    console.log(arr.flat(2)); // [1,2,3,4,5]
    ```
* forEach( )
  The `forEach()` method executes a provided function once for each array element.

  ```js
  let arr = [1, 2, 3];
  arr.forEach((element) => console.log(element * element)); // 1,4,9
  ```

* includes( )
  The `includes()` method determines whether an array includes a certain value among its entries, returning `true` or `false` as appropriate.

  ```js
  let arr = [1, 2, 3];
  console.log(arr.includes(2)); // true
  console.log(arr.includes(4)); // false
  ```

* join( )
  The `join()` method creates and returns a new string by concatenating all of the elements in an array, separated by commas or a specified separator string. If the array has only one item, then that item will be returned without using the separator.

  ```js
  const elements = ["Fire", "Air", "Water"];
  console.log(elements.join());
  // expected output: "Fire,Air,Water"
  console.log(elements.join(""));
  // expected output: "FireAirWater"
  console.log(elements.join("-"));
  // expected output: "Fire-Air-Water"
  ```

* map( )
  The `map()` method creates a new array populated with the results of calling a provided function on every element in the calling array.

  ```js
  let arr = [1, 2, 3];
  let newArr = arr.map((element) => element * 2);
  console.log(newArr); // [2,4,6]
  ```

* flatMap( )
  The `flatMap()` method returns a new array formed by applying a given callback function to each element of the array, and then flattening the result by one level. It is identical to a `map()` followed by a `flat()` of depth 1, but slightly more efficient than calling those two methods separately.

  ```js
  let arr = [1, 2, 3];
  let newArr = arr.flatMap((element) => [element * 2]);
  console.log(newArr); // [2,4,6]
  let newArr = arr.flatMap((element) => [[element * 2]]);
  console.log(newArr); // [[2],[4],[6]]
  ```

* pop( )
  The `pop()` method removes the <b>last</b> element from an array and returns that element. This method changes the length of the array.

  ```js
  let arr = [1, 2, 3];
  let lastElement = arr.pop();
  console.log(arr, lastElement); // [1,2] 3
  ```

* push( )
  The `push()` method adds one or more elements to the end of an array and returns the new length of the array.

  ```js
  let arr = [1, 2, 3];
  let length = arr.push(4, 5, 6);
  console.log(length, arr); // 6 [1,2,3,4,5,6]
  ```

* reduce( )
  The `reduce()` method executes a reducer function on each element of the array and returns a singel output value.
  The syntax of the `reduce()` method is:

  ```js
  reduce(function (accumulator, currentValue, currentIndex, array) {
    // callback - The function to execute on each array element(except the first element if no `initialValue` is provided). It takes in:
    // accumulator - It accumulates the callback's return values.
    // currentValue - The current element being passed from the array.
    // currentIndex is the index of the current value within the array.
    // array is a reference to the array reduce works on
    // initialValue(optional) - A value that will be passed to `callback()` on first call. If not provided, the first element acts as the `accumulator` on the first call and `callback()` won't execute on it.
  }, initialValue);
  ```

  <b>Note</b>:

  - Calling `reduce()` on an empty array without `initialValue` will throw `TyepError`.
  - `reduce()` executes the given function for each value of the array from left to right.
  - `reduce()` does not change the original array.
  - It is almost always <b>safer</b> to provide `initialValue`.

  ###

  Examples to explain `reduce()` in details.

  ```js
  // If there is no callback, reduce method return the value of initialValue.
  let value = [].reduce(() => {}, 2);
  console.log(value); // 2
  // If there is no initialValue, the first element of the array will be taken as the accumulator and callback function starts at the second element.
  value = [1, 0].reduce((accumulator, currentValue, currentIndex, arr) => {
    console.log(
      `callback: ${accumulator}, ${currentValue}, ${currentIndex}. arr: ${arr}`
    ); // callback: 1, 0, 1. arr: 1,0
    return accumulator + currentValue + currentIndex;
  });
  console.log(value); // 2
  ```

  <a href="https://www.programiz.com/javascript/library/array/reduce">Array.reduce( ) - programiz</a>
  <a href="https://blog.oliverjumpertz.dev/10-important-array-methods-in-javascript-explained#heading-7-reduce">Array.reduce( ) - oliver Jumpertz blog</a>

* reverse( )
  The `reverse()` method reverses an array in place(In computer science, an <b>in-place algorithm</b> is an algorithm which transforms input using no auxiliary data structure).
  ```js
  let arr = [1, 2, 3];
  console.log(arr.reverse()); // [3,2,1]
  ```
* shift( )
  The `shift()` method removes the <b>first</b> element from an array and returns that removed element. The method changes the length of the array.
  ```js
  let arr = [1, 2, 3];
  let firstElement = arr.shift();
  console.log(`firstElement: ${firstElement}, arr: ${arr}`); // firstElement: 1, arr: 2,3
  ```
* some( )
  The `some()` method tests whether at least one element in the array passes the test implemented by the provided function. It returns true if, in the array, it finds an element for which the provided function returns true; otherwise it returns false. It doesn't modify the array.
  ```js
  let arr = [1, 2, 3];
  console.log(arr.some((element) => element % 2 === 0)); // true
  ```
* sort( )
  The `sort()` method sorts the elements of an array in place and returns the sorted array.
  - sort from min to max(Default)
    ```js
    let arr = [1, 2, 3];
    console.log(arr.sort()); // [1,2,3]
    console.log(arr.sort((a, b) => a - b)); // [1,2,3]
    ```
  - sort from max to min
    ```js
    let arr = [1, 2, 3];
    console.log(arr.sort((a, b) => b - a)); // [3,2,1]
    ```
* unshift( )
  The `unshift()` method adds one or more elements to the beginning of an array and returns the new length of the array.
  ```js
  let arr = [4, 5];
  let length = arr.unshift(1, 2, 3);
  console.log(`length: ${length}, arr: ${arr}`); // length: 5, arr: [1,2,3,4,5]
  ```
* splice( )
  The `splice()` method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place. It returns an array which conains the deleted elements.
  Syntax: splice(start, deleteCount, item1, item2, itemN)

  - start - The index at which to start changing the array. If greater than the length of the array, `start` will be set to the length of the array. In this case, no element will be deleted but the method will behave as an adding function, adding as many elements as items provided. If negative, it will begin that many elements from the end of the array. (In this case, the origin `-1`, meaning `-n` is the index of the `n`th last elemtent, and is therefore equivalent to the index of `array.length - n`.) If `start` is `negative infinity`, it will begin from index `0`.

  ```js
  // start > array.length: act like an adding method
  arr = [1, 2, 3];
  let value = arr.splice(4, 0, "changed"); // deleteCount must have a value
  console.log(value, arr); // [] [1,2,3,'changed']

  // start < 0: start = array.length - start
  arr = [1, 2, 3];
  arr.splice(-2, 1, "changed");
  console.log(arr); // [1, 'changed', 3] (start = 1)
  arr.splice(Number.NEGATIVE_INFINITY, 1, "changed"); // [ 'changed', 'changed', 3 ]
  ```

  - deleteCount - An integer indicating the number of elements in the array to remove from `start`. If `deleteCount` is omitted, or if its value is equal to or larger than `array.length - start`, then all the elements from `start` to the end of the array will be deleted. However, it must not be omitted if there is any `item1` parameter. If `deleteCount` is `0` or negative, no elements are removed. In this case, you should specify at least one new element.

  ```js
  // deleteCount is omitted or its value >= array.length - start
  // all the elements from start to the end of the array will be deleted
  let arr = [1, 2, 3];
  arr.splice(1); // [1]
  arr.splice(2); // [1,2]
  arr.splice(3); // [1,2,3]
  arr.splice(1, 4); // [1]

  // deleteCount <= 0
  arr = [1, 2, 3];
  arr.splice(1, 0, 1.5); // [ 1, 1.5, 2, 3 ]
  arr.splice(1, -1, 1.5); // [ 1, 1.5, 2, 3 ]
  ```

  - item1, item2, ... - The elements to add to the array, beginning from `start`. If you do not specify any elements, `splice()` will only remove elements from the array.

  ```js
  // If you don't specify any elements, splice() will only remove
  let arr = [1, 2, 3];
  arr.splice(1, 1); // [1,3]
  ```