JavaScript 핵심 개념 요약: 데이터 타입, 객체 지향 및 이벤트 시스템

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로 들어가서 오류가 날 수 있음

태그: JavaScript frontend web-development event-loop Closure

7월 28일 18:33에 게시됨