1. 배열(Array) 자료구조와 주요 메서드
JavaScript 배열은 하나의 변수에 여러 데이터를 저장하는 리스트 형태의 객체입니다. Array.prototype에 정의된 다양한 메서드를 통해 데이터를 조작할 수 있습니다.
배열 수정 및 추출 메서드
- push / pop: 배열의 끝에 요소를 추가하거나 마지막 요소를 제거합니다.
- unshift / shift: 배열의 처음에 요소를 추가하거나 첫 번째 요소를 제거합니다.
- splice(index, count, items): 특정 위치의 요소를 삭제하거나 새로운 요소를 삽입하여 원본 배열을 수정합니다.
- slice(start, end): 배열의 일부분을 복사하여 새로운 배열을 반환합니다. 원본은 변경되지 않습니다.
- concat: 두 개 이상의 배열을 결합하여 새 배열을 생성합니다.
const fruits = ['apple', 'banana', 'cherry'];
const moreFruits = ['orange', 'grape'];
// 배열 결합
const combined = fruits.concat(moreFruits);
// 특정 범위 추출
const subFruits = combined.slice(1, 4); // ['banana', 'cherry', 'orange']
// 요소 수정 (index 2부터 1개 삭제 후 'mango' 추가)
combined.splice(2, 1, 'mango');
console.log(combined); // ['apple', 'banana', 'mango', 'orange', 'grape']
배열 정렬 및 문자열 변환
- sort(callback): 배열의 요소를 정렬합니다. 기본적으로 문자열의 유니코드 순서로 정렬하므로, 숫자를 정렬할 때는 비교 함수를 전달해야 합니다.
- join(separator): 배열의 모든 요소를 하나의 문자열로 합칩니다.
const scores = [10, 5, 100, 25];
scores.sort((a, b) => a - b); // 오름차순 정렬: [5, 10, 25, 100]
const csv = scores.join(', '); // "5, 10, 25, 100"
2. 문자열(String) 처리
문자열은 텍스트 데이터를 처리하는 데 사용되며, 불변(Immutable)의 성질을 가집니다.
- indexOf / lastIndexOf: 특정 부분 문자열의 첫 번째 또는 마지막 위치를 검색합니다.
- match / search / replace: 정규표현식을 사용하여 패턴 매칭, 검색, 치환을 수행합니다.
- split: 구분자를 기준으로 문자열을 분할하여 배열로 변환합니다.
- substring / substr: 특정 구간의 문자열을 추출합니다.
const phrase = "Hello JavaScript World";
console.log(phrase.indexOf("Java")); // 6
console.log(phrase.replace("World", "Developer")); // "Hello JavaScript Developer"
console.log(phrase.split(" ")); // ["Hello", "JavaScript", "World"]
3. 정규 표현식(RegExp)
텍스트 패턴을 정의하고 검색하는 데 사용됩니다.
- test(): 패턴 일치 여부를 논리값(true/false)으로 반환합니다.
- exec(): 일치하는 정보를 담은 배열을 반환하거나 일치하지 않으면 null을 반환합니다.
const pattern = /web/i; // 대소문자 구분 없음
const result = pattern.test("Welcome to the Web world"); // true
4. JavaScript 객체와 프로토타입
JavaScript의 거의 모든 것은 객체입니다. 객체는 속성(Property)과 메서드(Method)의 집합입니다.
객체 생성 방식
// 리터럴 방식
const user = {
name: 'Alice',
greet: function() { console.log('Hi ' + this.name); }
};
// 생성자 함수 방식
function Member(id, email) {
this.id = id;
this.email = email;
}
const member1 = new Member('dev123', 'test@example.com');
5. 브라우저 이벤트 시스템
이벤트 흐름은 캡처링(Capturing)과 버블링(Bubbling) 단계로 나뉩니다.
- 이벤트 버블링: 하위 요소에서 발생한 이벤트가 상위 요소로 전파되는 현상입니다.
- 이벤트 캡처링: 최상위 요소에서 시작하여 실제 이벤트가 발생한 타겟 요소까지 내려가는 과정입니다.
- 이벤트 위임(Delegation): 개별 요소가 아닌 부모 요소에 이벤트 리스너를 등록하여 성능을 최적화하고 동적 요소를 처리하는 기법입니다.
표준 이벤트 핸들링 예제
const container = document.getElementById('parent');
container.addEventListener('click', function(event) {
// 이벤트 위임 처리
if (event.target.tagName === 'TD') {
console.log('클릭된 셀의 내용:', event.target.innerText);
event.stopPropagation(); // 전파 방지
}
}, false); // false는 버블링 단계에서 실행됨을 의미
6. 클로저(Closure)와 스코프
클로저는 함수가 선언된 당시의 환경(Lexical Environment)을 기억하여, 함수가 외부 스코프 밖에서 호출되어도 해당 스코프의 변수에 접근할 수 있는 메커니즘입니다.
function createCounter() {
let count = 0; // 은닉된 변수
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
클로저는 데이터 은닉과 캡슐화를 구현하고, 상태를 안전하게 유지하는 데 핵심적인 역할을 합니다.
7. this 바인딩의 이해
JavaScript에서 this는 함수가 어떻게 호출되었는지에 따라 동적으로 결정됩니다.
- 전역 호출:
window(엄격 모드에서는undefined) - 메서드 호출: 해당 메서드를 호출한 객체
- 생성자 호출: 새로 생성되는 인스턴스
- 명시적 바인딩:
call,apply,bind메서드를 통해 강제로 지정
const module = {
x: 42,
getX: function() { return this.x; }
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // undefined (전역 호출 상황)
const boundGetX = unboundGetX.bind(module);
console.log(boundGetX()); // 42
8. null과 undefined의 차이
- undefined: 변수가 선언되었으나 값이 할당되지 않았음을 의미하는 시스템 수준의 기본값입니다.
- null: 의도적으로 '값이 없음'을 명시하는 할당값입니다. 객체가 있어야 할 자리에 객체가 없음을 나타낼 때 주로 사용됩니다.
9. 고차 함수: map()과 forEach()
배열을 순회하는 두 메서드는 용도가 다릅니다.
- forEach: 각 요소에 대해 함수를 실행하지만, 반환값은 항상
undefined입니다. - map: 각 요소에 함수를 적용한 결과로 새로운 배열을 생성하여 반환합니다.
const originArr = [1, 2, 3];
// map 사용 시 주의점: parseInt와 결합
const newArr = ["1", "2", "3"].map(num => parseInt(num, 10));
// 단순히 .map(parseInt)를 쓰면 인덱스 값이 radix로 들어가서 오류가 날 수 있음