자바스크립트는 처음 배포 당시 배열을 포함시키지 못했습니다. 자바스크립트의 객체가 워낙 강력해서 배열이 빠졌다는 사실을 알아채는 경우는 드물었지만요. 성능 문제만 무시한다면 객체는 배열이 할 수 있는 모든 것을 할 수 있습니다.
더글러스 크락포드 , 『자바스크립트는 왜 그 모양일까?』, 인사이트(2020), p81.
이처럼 자바스크립트의 배열은 엄밀히 말해 일반적 의미의 배열이 아니다. 자바스크립트의 배열은 일반적인 배열의 동작을 흉내 낸 특수한 객체다.
이웅모 , 『모던 자바스크립트 Deep Dive』, 위키북스(2020), p496.
1960년대 중반, 작지만 영향력 있는 개발자 그룹이 1 대신 0부터 시작하면 어떻겠느냐고 제안했습니다. 그래서 오늘날 거의 모든 개발자는 수를 셀 때 0부터 시작합니다. …0에서 시작하는 것이 off-by-one 에러를 유발하기 때문에 정확하지 않다는 주장도 있지만, 이 또한 확실하지는 않습니다.
더글러스 크락포드 , 『자바스크립트는 왜 그 모양일까?』, 인사이트(2020), p82.
배열을 다룰 때는 한 번에 하나의 요소만 처리해야 한다는 생각은 최소한 포트란 시절까지는 거슬러 올라가야 맞는 말입니다. 최근에는 배열 요소를 한 번에 하나씩 처리하기보다, 배열을 좀 더 함수처럼 처리해야 한다는 생각이 더 지배적입니다. 이렇게 해야 명시적인 반복문 처리가 없어져서 코드가 단순해지고, 멀티프로세서에 작업을 분산해서 처리할 수 있는 능력이 생깁니다. 잘 설계된 언어로 잘 짜이니 프로그램은 배열이 0에서 시작하든 1에서 시작하든 신경 쓸 필요가 없습니다.
더글러스 크락포드 , 『자바스크립트는 왜 그 모양일까?』, 인사이트(2020), p82-83.
현재 length 프로퍼티 값보다 작은 숫자를 할당하면 배열의 길이는 줄어든다.
const arr = [1, 2, 3];
arr.length = 2;
console.log(arr); // [1, 2]
현재 length 프로퍼티 값보다 큰 숫자를 할당하면 배열 마지막에 빈 영역이 생기지만 실제 새 요소가 추가되지는 않는다.
const arr = [1];
arr.length = 3;
console.log(arr); // [1, empty * 2]
const arr = [1, 2, 3];
const arr2 = [1, ,3];
console.log(arr2); // [1, empty, 3]
let a = new Array();
let a = new Array(10);
let a = new Array(1, 2, 3, "testing");
Array.of(10) // [10]
Array.from({ length: 2, 0: 'a', 1: 'b' }); // ['a', 'b']
const arr = [1, 2, 3];
arr.indexOf(2); // 1
arr.indexOf(4); // -1
arr.includes(2); // true
arr.includes(4); // false
[NaN].indexOf(NaN) !== -1; // false
[NaN].includes(NaN); // true
const arr1 = [1, 2];
const arr2 = [3, 4];
console.log(arr1.concat(arr2)); // [1, 2, 3, 4]
.splice(start, deleteCount, items)
const arr = [1, 2, 3, 4];
const res = arr.splice(1, 2, 20, 30);
console.log(res); // [2, 3]
console.log(arr); // [1, 20, 30, 4]
const arr = [1, 2, 3];
arr.slice(0, 1); // [1]
const arr = [1, 2, 3];
arr.fill(0); // [0, 0, 0]
const arr = [1, 2, 3, 4];
arr.join(); // '1,2,3,4'
[1, [2, 3, 4, 5]].flat(); // [1, 2, 3, 4, 5]
[1, [2, [3, [4]]]].flat(2); // [1, 2, 3, [4]]
고차 함수는 외부 상태의 변경이나 가변(mutable) 데이터를 피하고 불변성(immutable)을 지향하는 함수형 프로그래밍에 기반을 두고 있다.
함수형 프로그래밍은 순수 함수(pure function)와 보조 함수의 조합을 통해 로직 내에 존재하는 조건문과 반복문을 제거하여 복잡성을 해결하고 변수의 사용을 억제하여 상태 변경를 피하려는 프로그래밍 패러다임이다. 조건문이나 반복문은 로직의 흐름을 이해하기 어렵게 하여 가독성을 해치고, 변수는 누군가에 의해 언제든지 변경될 수 있어 오류 발생의 근본적 원인이 될 수 있기 때문이다. 함수형 프로그래밍은 결국 순수 함수를 통해 부수 효과를 최대한 억제하여 오류를 피하고 프로그램의 안정성을 높이려는 노력의 일환이라고 할 수 있다.
이웅모 , 『모던 자바스크립트 Deep Dive』, 위키북스(2020), p529.
자바스크립트의 sort 메서드에는 몇 가지 문제가 있습니다. sort 메서드는 추가 메모리 공간을 사용하지 않고 배열 자체를 수정합니다. …다음 문제점은 안정성이 부족하다는 것입니다. 배열의 요소를 비교했을 때 같은 값, 즉 비교 함수가 영(0)을 반환하는 경우 두 요소의 상대적인 위치를 그대로 유지한다면 sort 함수는 안정적입니다. 하지만 자바스크립트는 안정성을 보장하지 않습니다.
더글러스 크락포드 , 『자바스크립트는 왜 그 모양일까?』, 인사이트(2020), p89-90
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(callback, thisArg) {
// 첫 번째 인수가 함수가 아니면 TypeError 발생
if(typeof callback !== 'function'){
throw new TypeError(callback + 'is not a function');
}
// this로 사용할 두 번째 인수를 받지 못하면 전역 객체를 this로 사용한다.
thisArg = thisArg || window;
for(var i = 0; i < this.length; i++) {
// call 메서드를 통해 thisArg를 전달하면서 콜백 함수를 호출한다.
callback.call(thisArg, this[i], i, this);
}
};
}
const arr = [1, 2, 3, 4];
const sum = arr.reduce((accumulator, currentValue, index, array) => {
return accumulator + currentValue
}, 0);
console.log(sum); // 10
const arr = ['hello', 'world'];
arr.map(x => x.split('')).flat();
// ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
arr.flatMap(x => x.split(''));
// ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
References
데이비드 플래너건 , 『자바스크립트 완벽 가이드』, 인사이트(2022)
더글러스 크락포드 , 『자바스크립트는 왜 그 모양일까?』, 인사이트(2020)
카일 심슨 , 『You Don’t Know JS - 타입과 문법, 스코프와 클로저』, 한빛미디어(2017)
이웅모 , 『모던 자바스크립트 Deep Dive』, 위키북스(2020)