Web/JavaScript

[JavaScript] Array

llHoYall 2022. 7. 6. 21:39

Arrays in JS are sparse array that is not continuously connected in memory.

Compared to a typical array, accessing the index is fast, and inserting/deleting is slow.

Neither JS arrays' length nor its elements' types are fixed.

Create Arrays

There are 4 ways to create arrays.

Array Literal

const arr1 = [1, 2, 3];
const arr2 = ["apple", 2, "carrot", 4];

Array Constructor

const arr = new Array(3); // [empty x 3]
const arr2 = new Array(1, 2, 3); // [1, 2, 3]

of() Method

const arr = Array.of(3); // [3]
const arr2 = Array.of(1, 2, 3); // [1, 2, 3]

from() Method

We can create an array using an array-like object through this method.

const arr = Array.from('test'); // ['t', 'e', 's', 't']
const arr2 = Array.from({ length: 3, 0: 1, 1: 2, 2: 3 }); // [1, 2, 3]
const arr3 = Array.from({ length: 3 }, (_, i) => i); // [0, 1, 2]

Properties of Arrays

length

let arr = [1, 2, 3];
console.log(`[${arr}]: ${arr.length}`);
// [1, 2, 3]: 3

arr.length = 7;
console.log(`[${arr}]: ${arr.length}`);
// [1, 2, 3, , , , ]: 7

arr.length = 2;
console.log(`[${arr}]: ${arr.length}`);
// [1, 2]: 2

The length property returns the number of the array's elements.

You can directly manipulate this property and the array will be changed.

Check Arrays

We can check whether it is an array using the isArray() method.

// true
Array.isArray([]);
Array.isArray(new Array());
Array.isArray([1, 2]);

// false
Array.isArray();
Array.isArray({});
Array.isArray(null);
Array.isArray(undefined);
Array.isArray(1);
Array.isArray('array');
Array.isArray(true);
Array.isArray(false);
Array.isArray({ 0: 1, length: 1 });

We can also check whether it is an element of the arrays using indexOf() and includes() methods.

const fruits = ['apple', 'banana', 'cherry'];

if (fruits.indexOf('durian') === -1) {
  console.log('Not Found');
}

if (fruits.includes('eggplant')) {
  console.log('Found');
}

// Check from index 1
if (fruits.includes('cherry', 1)) {
  console.log('Found');
}

indexOf() method returns an index if the argument is in the array, and returns -1 if not.

Access to Arrays

We can access elements of arrays through the [] operator with index.

It returns undefined if we try to access nonexistence elements.

const arr = [1, 2, 3, 4, 5];

arr[2]; // 3
arr[10]; // undefined

Find Elements

We can find elements of arrays through the indexOf() method with the value we want to find.

It returns the index of the element it finds.

As seen above, if not found, it returns -1.

const arr = [1, 2, 3, 4, 3, 2, 1];

arr.indexOf(2); // 1
arr.indexOf(5); // -1

// find value 2 from index 3
arr.indexOf(2, 3); // 5

The second argument means from where to find the value if it exists.

lastIndexOf() method are reverse direction of indexOf() method.

const arr = [1, 2, 3, 4, 3, 2, 1];

arr.lastIndexOf(2); // 5
arr.lastIndexOf(5); // -1

// find value 2 from index 3
arr.lastIndexOf(2, 3); // 1

Add Elements

push() Method

This method appends elements to the last of the array.

It has a side effect that changes original arrays.

const arr = [];

arr.push(1); // returns: 1
// arr: [1]

arr.push(2, 3); // returns: 3
// arr: [1, 2, 3]

arr.push([4, 5]); // returns: 4 (length)
// arr: [1, 2, 3, [4, 5]]

In addition, this method does not have a good performance, so if there is only one element to add, the following way is recommended.

const arr = [];

arr[arr.length] = 1; // returns: 1
// arr: [1]

unshift() Method

This method adds elements to the start of the array.

And, this method also has a side effect and is slower than the push() method.

const arr = [];

arr.unshift(1); // returns: 1 (length)
// arr: [1]

arr.unshift(2, 3); // returns: 3 (length)
// arr: [2, 3, 1]

arr.unshift([4, 5]); // returns: 4 (length)
// arr: [[4, 5], 2, 3, 1]

concat() Method

This method has no side effects and can replace push() and unshift() methods.

const arr = [];

const arr2 = arr.concat(1);
// arr2: [1]

const arr3 = arr2.concat(2, 3);
// arr3: [1, 2, 3]

const arr4 = arr3.concat([4, 5]);
// arr4: [1, 2, 3, 4, 5]

const arr5 = [6, 7].concat(arr4);
// arr5: [6, 7, 1, 2, 3, 4, 5]

Spread Operator

This method has no side effects and is easy to understand.

Therefore, it is recommended.

In addition, it can cover all the above methods.

const arr = [];

const arr2 = [...arr, 1];
// arr2: [1]

const arr3 = [...arr2, [2, 3]];
// arr3: [1, [2, 3]]

const arr4 = [-2, -1, ...arr3];
// arr4: [-2, -1, 1, [2, 3]]

const arr5 = [-3, ...arr4, 4];
// arr5: [-3, -2, -1, 1, [2, 3], 4]

Delete Elements

pop() Method

This method returns the last element of the array and deletes it.

It has a side effect.

const arr = [1, 2, 3, 4, 5];

arr.pop(); // 5
// arr: [1, 2, 3, 4]

We can delete elements in the middle of the element.

It only deletes the element's value, so be careful when using this way.

const arr = [1, 2, 3, 4, 5];

delete arr[2]; // true
// arr: [1, 2, empty, 4, 5]

shift() Method

This method returns the first element of the array and deletes it.

It has a side effect.

const arr = [1, 2, 3, 4, 5];

arr.shift(); // 1
// arr: [2, 3, 4, 5]

Splice and Slice

The splice() method adds or deletes a specific number of elements from a particular location.

It has a side effect.

const arr = [1, 2, 3, 4, 5];

// Delete 2 elements from index 1
arr.splice(1, 2); // [2, 3]
// arr: [1, 4, 5]

// Delete 2 elements from index 1 and insert 6 into there
arr.splice(1, 2, 6); // [4, 5]
// arr: [1, 6]

// Delete nothing and insert [2, 3] into index 1
arr.splice(1, 0, [2, 3]); // []
// arr: [1, [2, 3], 6]

// Delete all elements from index 1
arr.splice(1); // [[2, 3], 6]
// arr: [1]

The slice() method creates a new array with a specific number of elements from a particular location.

Therefore, it has no side effects.

const arr = [1, 2, 3, 4, 5];

// Copy from index 1
const arr2 = arr.slice(1);
// arr2: [2, 3, 4, 5]

// Copy index 0 ~ index 3 (not included)
const arr3 = arr2.slice(0, 3);
// arr3: [2, 3, 4]

// Copy 2 elements from the end
const arr4 = arr3.slice(-2);
// arr4: [3, 4]

// Shallow copy
const arr5 = arr4.slice();
// arr5: [3, 4]

Array Methods

join() Method

This method converts all elements to strings and joins them with a separator.

The default separator is a comma.

It has no side effects.

const arr = [1, 2, 3, 4, 5];

arr.join(); // 1,2,3,4,5
arr.join('-'); // 1-2-3-4-5
arr.join(''); // 12345
// arr: [1, 2, 3, 4, 5]

fill() Method

This method fills the elements' values to the designated value.

It has a side effect.

const arr = [1, 2, 3, 4, 5];

arr.fill(0);
// arr: [0, 0, 0, 0, 0]

// Fill 7 from index 2
arr.fill(7, 2);
// arr: [0, 0, 7, 7, 7]

// Fill 5 from index 1 ~ index 3 (not included)
arr.fill(5, 1, 3);
// arr: [0, 5, 5, 7, 7]

flat() Method

This method flattens the array recursively by the argument.

The default depth is 1.

It has no side effects.

const arr = [1, [2, [3, [4, [5]]]]];

const arr2 = arr.flat();
// arr2:[1, 2, [3, [4, [5]]]]

const arr3 = arr.flat(2);
// arr3: [1, 2, 3, [4, [5]]]

const arr4 = arr.flat(Infinity);
// arr4: [1, 2, 3, 4, 5]

reverse() Method

This method reverses the array.

It has a side effect.

const arr = [1, 2, 3, 4, 5];

arr.reverse(); // [5, 4, 3, 2, 1]
// arr: [5, 4, 3, 2, 1]

High-Order Methods

High-Order methods are methods that can be input by function.

forEach() Method

This method traverses the array.

const arr = [1, 2, 3];
const pow = [];

arr.forEach(
  elem => pow[pow.length] = (elem ** 2)
);
// pow: [ 1, 4, 9 ]

find() Method

This method returns the value of the first element found.

const users = [
  { id: 1, name: "HoYa" },
  { id: 2, name: "Kim" },
  { id: 3, name: "Park" },
  { id: 1, name: "Lee" },
];

users.find(elem => elem.id === 1);
// { id: 1, name: 'HoYa' }

findIndex() Method

This method returns the index of the first element found.

const users = [
  { id: 1, name: "HoYa" },
  { id: 2, name: "Kim" },
  { id: 3, name: "Park" },
  { id: 1, name: "Lee" },
];

console.log(users.findIndex(elem => elem.name === 'Park'));
// 2

function getByKey(key, value) {
  return elem => elem[key] === value;
}

console.log(users.findIndex(getByKey('name', 'HoYa')));
// 0

sort() Method

This method has a side effect.

If the return value of the comparator function is less than 0, it sorts using the first argument, if it is 0, it doesn't sort, and if it is greater than 0, it sorts using the second argument.

const arr = [3, 1, 2];

// ascending
arr.sort();
// arr: [ 1, 2, 3 ]

// descending
arr.sort((x, y) => y - x);
// arr: [ 3, 2, 1 ]

map() Method

This method creates a new array populated with the results of the provided function on every element in the array.

const arr = [1, 2, 3];

const arr2 = arr.map(elem => elem * 2);
// arr2: [ 2, 4, 6 ]

filter() Method

This method creates a new array with all elements that pass the test implemented by the provided function.

const arr = [1, 2, 3, 4, 5];

const arr2 = arr.filter(elem => elem % 2);
// arr2: [ 1, 3, 5 ]

reduce() Method

This method executes a provided reducer function on each element of the array, resulting in a single output value.

const arr = [1, 2, 3, 4, 5];

const sum = arr.reduce((acc, val) => acc + val, 0);
// 15 <- 0 + 1 + 2 + 3 + 4 + 5

const average = arr.reduce(
  (acc, cur, idx, { length }) =>
    idx === length - 1 ? (acc + cur) / length : acc + cur,
  0
);
// 3

const fruits = ["apple", "banana", "cherry", "banana", "apple"];

const counts = fruits.reduce((acc, cur) => {
  acc[cur] = (acc[cur] || 0) + 1;
  return acc;
}, {});
// { apple: 2, banana: 2, cherry: 1 }

reduceRight() Method

Unlike reduce() method, this method applies from the last element.

const arr = [1, 2, 3, 4, 5];

const sum = arr.reduceRight((acc, val) => acc - val, 0);
// -15 <- 0 - 5 - 4 - 3 - 2 - 1

some() Method

This method returns true if at least one element of the array is satisfied with the given testing function, otherwise returns false.

const arr = [1, 2, 3, 4, 5];

arr.some(elem => elem > 4); // true

every() Method

This method returns true if all elements of the array are satisfied with the given testing function, otherwise returns false.

const arr = [1, 2, 3, 4, 5];

arr.every(elem => elem < 7); // true

flatMap() Method

This method is added in ES10.

It has the effect of executing the map() method and flat() method in order.

But, it only flattens by 1 depth.

const arr = ['hello', 'world'];

const arr2 = arr.flatMap(x => x.split(''));
// arr2: [ 'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd' ]