typeof와 instanceof의 핵심 구현 원리

  1. typeof의 핵심 구현 원리

자바스크립트 내부의 타입 태그 메커니즘

자바스크립트 엔진 내부에서는 각 값이低位비트에 타입 태그(type tag)로 저장되어 있습니다. 이를 통해 typeof 연산자는 빠른 시간 내에 값의 타입을 식별할 수 있습니다.

// typeof의 내부 로직을 모방한 구현
function detectType(value) {
    // 1. null 값에 대한 예외 처리
    if (value === null) {
        return 'object';
    }
    
    // 2. 함수 객체에 대한 특수 처리
    if (typeof value === 'function') {
        return 'function';
    }
    
    // 3. 내부 [[Class]] 속성을 기반으로 타입 판별
    const internalType = Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
    
    // 4. undefined에 대한 처리
    if (value === undefined) {
        return 'undefined';
    }
    
    // 5. 기본 타입 매핑 테이블
    const typeMapping = {
        number: 'number',
        string: 'string',
        boolean: 'boolean',
        symbol: 'symbol',
        bigint: 'bigint',
        object: 'object'
    };
    
    return typeMapping[internalType] || 'object';
}

실제 엔진에서의 구현 개요

// V8 엔진 기반 타입 판별 로직
function V8Detect(value) {
    // 내부 클래스 정보 조회
    const classInfo = %_ClassOf(value);
    
    switch (classInfo) {
        case 'Number': return 'number';
        case 'String': return 'string';
        case 'Boolean': return 'boolean';
        case 'Symbol': return 'symbol';
        case 'BigInt': return 'bigint';
        case 'Function': return 'function';
        case 'Undefined': return 'undefined';
        case 'Null': return 'object'; // 역사적 원인
        default: return 'object';
    }
}

typeof의 특수 동작 설명

// 역사적 문제로 인한 동작
typeof null === 'object' // true

// 함수对象的 특수 처리
typeof function() {} === 'function' // true
typeof class {} === 'function'      // true

// 기타 객체들
typeof [] === 'object'              // true
typeof {} === 'object'              // true
typeof new Date() === 'object'      // true

  1. instanceof의 핵심 구현 원리

instanceof의底层实现

// instanceof의 폴리필 구현
function checkInstance(target, constructor) {
    // 1. 기본 타입은 즉시 false 반환
    if (target === null || typeof target !== 'object' && typeof target !== 'function') {
        return false;
    }
    
    // 2. 대상 객체의 프로토타입 참조 획득
    let prototypeChain = Object.getPrototypeOf(target);
    
    // 3. 프로토타입 체인 순회
    while (prototypeChain !== null) {
        // 4. 생성자의 프로토타입과 일치하면 true 반환
        if (prototypeChain === constructor.prototype) {
            return true;
        }
        // 5. 상위 프로토타입으로 이동
        prototypeChain = Object.getPrototypeOf(prototypeChain);
    }
    
    // 6. 체인 끝까지 없으면 false 반환
    return false;
}

경계 상황을 포함한 완전한 구현

function fullInstanceofCheck(target, constructor) {
    // 생성자 유효성 검증
    if (typeof constructor !== 'function') {
        throw new TypeError('오른쪽 피연산자는 함수가 아닙니다');
    }
    
    // null이 아닌 객체 또는 함수인지 확인
    if (target === null || (typeof target !== 'object' && typeof target !== 'function')) {
        return false;
    }
    
    // 생성자의 프로토타입 참조
    const constructorPrototype = constructor.prototype;
    
    // 프로토타입이 유효한 객체가 아니면 예외 발생
    if (typeof constructorPrototype !== 'object' && constructorPrototype !== null) {
        throw new TypeError('프로토타입이 유효하지 않습니다');
    }
    
    // 프로토타입 체인 탐색
    let current = Object.getPrototypeOf(target);
    while (current !== null) {
        if (current === constructorPrototype) {
            return true;
        }
        current = Object.getPrototypeOf(current);
    }
    
    return false;
}

  1. 실전 활용 예제

typeof 활용 시나리오

function analyzeValue(data) {
    const typeInfo = typeof data;
    
    switch (typeInfo) {
        case 'string':
            return `문자열: ${data}`;
        case 'number':
            return `숫자: ${data}`;
        case 'boolean':
            return `불리언: ${data}`;
        case 'undefined':
            return '미정의 상태';
        case 'function':
            return '함수';
        default:
            if (data === null) return 'null';
            return `객체: ${data.constructor.name}`;
    }
}

console.log(analyzeValue('hello'));    // 문자열: hello
console.log(analyzeValue(42));         // 숫자: 42
console.log(analyzeValue(null));       // null

instanceof 활용 시나리오

class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

const dog = new Dog();
const cat = new Cat();

console.log(checkInstance(dog, Dog));     // true
console.log(checkInstance(dog, Animal));  // true
console.log(checkInstance(dog, Cat));     // false
console.log(checkInstance([], Array));    // true
console.log(checkInstance([], Object));   // true

  1. 성능 최적화 버전

캐시를 활용한 최적화 구현

function createOptimizedChecker() {
    const memoCache = new WeakMap();
    
    return function(target, constructor) {
        // 기본 타입 빠른 경로
        if (target === null || typeof target !== 'object') {
            return false;
        }
        
        // 캐시 키 생성
        const cacheKey = `${constructor.name}-${typeof target}`;
        if (memoCache.has(cacheKey)) {
            return memoCache.get(cacheKey);
        }
        
        // 프로토타입 체인 탐색
        let chain = Object.getPrototypeOf(target);
        while (chain !== null) {
            if (chain === constructor.prototype) {
                memoCache.set(cacheKey, true);
                return true;
            }
            chain = Object.getPrototypeOf(chain);
        }
        
        memoCache.set(cacheKey, false);
        return false;
    };
}

const fastInstanceof = createOptimizedChecker();

  1. 핵심 차이점 요약

특성 typeof instanceof
검사 대상 값의 타입 프로토타입 체인 관계
반환값 문자열 불리언
null 처리 'object' 반환 false 반환
성능 O(1) O(n) - 체인 길이
적합한场景 기본 타입 검사 상속 관계 검사

실무 사용 권장사항

// 기본 타입 검사에는 typeof 사용
if (typeof variable === 'string') {
    // 문자열 처리
}

// 객체 타입 및 상속 관계 검사에는 instanceof 사용
if (variable instanceof Error) {
    // 에러 객체 처리
}

// 배열 검사는 Array.isArray 권장
if (Array.isArray(variable)) {
    // 배열 처리
}

태그: JavaScript typeof instanceof Prototype type-checking

7월 1일 21:33에 게시됨