引言:类型检测的复杂性与重要性

在 JavaScript 开发中,准确判断数据类型是构建健壮应用的基础。特别是对象类型的检测,看似简单实则暗藏诸多陷阱。本文将深入探讨从基础方法到企业级解决方案的完整对象检测体系。

基础检测方法深度分析

typeof 运算符的局限性

// typeof 运算符的完整行为分析
class TypeofAnalysis {
    constructor() {
        this.typeofBehaviors = {
            primitiveTypes: {
                undefined: 'undefined',
                null: 'object', // 著名的历史遗留问题
                boolean: 'boolean',
                number: 'number',
                string: 'string',
                symbol: 'symbol',
                bigint: 'bigint'
            },
            
            objectTypes: {
                object: 'object',           // 普通对象
                array: 'object',           // 数组
                function: 'function',      // 函数
                date: 'object',            // 日期
                regexp: 'object',          // 正则表达式
                error: 'object',           // 错误对象
                arguments: 'object'        // arguments 对象
            },
            
            specialCases: {
                NaN: 'number',             // NaN 也是 number
                Infinity: 'number',        // 无穷大也是 number
                new Boolean(false): 'object', // 包装对象
                new Number(0): 'object',
                new String(''): 'object'
            }
        };
    }
    
    demonstrateTypeofLimitations() {
        const testCases = [
            { value: null, expected: 'null', actual: typeof null },
            { value: [], expected: 'array', actual: typeof [] },
            { value: new Date(), expected: 'date', actual: typeof new Date() },
            { value: /regex/, expected: 'regexp', actual: typeof /regex/ },
            { value: document.createElement('div'), expected: 'htmlelement', actual: typeof document.createElement('div') }
        ];
        
        return testCases.map(test => ({
            ...test,
            accurate: test.expected === test.actual,
            limitation: test.expected !== test.actual ? '无法区分具体对象类型' : '准确'
        }));
    }
    
    // typeof 的安全使用模式
    createSafeTypeofChecker() {
        class SafeTypeofChecker {
            static isUndefined(value) {
                return typeof value === 'undefined';
            }
            
            static isString(value) {
                return typeof value === 'string';
            }
            
            static isNumber(value) {
                return typeof value === 'number' && !isNaN(value);
            }
            
            static isFunction(value) {
                return typeof value === 'function';
            }
            
            static isSymbol(value) {
                return typeof value === 'symbol';
            }
            
            // 特别注意:这不是可靠的对象检测方法
            static isObjectUnsafe(value) {
                return typeof value === 'object'; // 有问题的实现
            }
        }
        
        return SafeTypeofChecker;
    }
}

instanceof 操作符的原理与局限

// instanceof 深度解析
class InstanceofAnalysis {
    constructor() {
        this.instanceofMechanism = {
            prototypeChain: '沿着原型链向上查找',
            constructorComparison: '比较构造函数的prototype属性',
            crossRealmIssues: '跨域iframe、多全局环境问题'
        };
    }
    
    demonstrateInstanceofBehavior() {
        // 基础用例
        const baseCases = [
            { value: {}, constructor: Object, result: {} instanceof Object },
            { value: [], constructor: Array, result: [] instanceof Array },
            { value: () => {}, constructor: Function, result: (() => {}) instanceof Function },
            { value: new Date(), constructor: Date, result: new Date() instanceof Date }
        ];
        
        // 继承用例
        class Animal {}
        class Dog extends Animal {}
        const dog = new Dog();
        
        const inheritanceCases = [
            { value: dog, constructor: Dog, result: dog instanceof Dog },
            { value: dog, constructor: Animal, result: dog instanceof Animal },
            { value: dog, constructor: Object, result: dog instanceof Object }
        ];
        
        // 边界用例
        const edgeCases = [
            { 
                value: Object.create(null), 
                constructor: Object, 
                result: Object.create(null) instanceof Object,
                note: '无原型对象的instanceof行为'
            },
            {
                value: null,
                constructor: Object,
                result: null instanceof Object,
                note: 'null的instanceof行为'
            },
            {
                value: undefined,
                constructor: Object, 
                result: undefined instanceof Object,
                note: 'undefined的instanceof行为'
            }
        ];
        
        return { baseCases, inheritanceCases, edgeCases };
    }
    
    // instanceof 的跨域问题演示
    demonstrateCrossRealmIssue() {
        // 模拟跨域场景
        const iframe = document.createElement('iframe');
        document.body.appendChild(iframe);
        
        const iframeArray = iframe.contentWindow.Array;
        const localArray = [];
        
        const crossRealmResults = {
            sameConstructor: localArray.constructor === iframeArray,
            instanceofLocal: localArray instanceof Array,
            instanceofIframe: localArray instanceof iframeArray,
            constructorName: localArray.constructor.name,
            iframeConstructorName: iframeArray.name
        };
        
        document.body.removeChild(iframe);
        
        return crossRealmResults;
    }
    
    // 安全的 instanceof 实现
    createSafeInstanceofChecker() {
        class SafeInstanceofChecker {
            static safeInstanceof(value, constructor) {
                if (value == null) {
                    return false;
                }
                
                // 基础类型检查
                if (typeof value !== 'object' && typeof value !== 'function') {
                    return false;
                }
                
                // 标准 instanceof 检查
                if (value instanceof constructor) {
                    return true;
                }
                
                // 处理跨域情况
                const prototype = constructor.prototype;
                if (!prototype) {
                    return false;
                }
                
                // 手动检查原型链
                let current = Object.getPrototypeOf(value);
                while (current !== null) {
                    if (current === prototype) {
                        return true;
                    }
                    current = Object.getPrototypeOf(current);
                }
                
                return false;
            }
            
            // 针对常见类型的快捷方法
            static isPlainObject(value) {
                return this.safeInstanceof(value, Object) && 
                       Object.getPrototypeOf(value) === Object.prototype;
            }
            
            static isArray(value) {
                return this.safeInstanceof(value, Array);
            }
            
            static isDate(value) {
                return this.safeInstanceof(value, Date);
            }
            
            static isRegExp(value) {
                return this.safeInstanceof(value, RegExp);
            }
        }
        
        return SafeInstanceofChecker;
    }
}

中级检测方案

Object.prototype.toString 方法

// toString 类型检测系统
class ToStringTypeDetection {
    constructor() {
        this.standardTags = {
            '[object Object]': '普通对象',
            '[object Array]': '数组',
            '[object Function]': '函数',
            '[object Date]': '日期',
            '[object RegExp]': '正则表达式',
            '[object Error]': '错误对象',
            '[object Promise]': 'Promise',
            '[object Map]': 'Map',
            '[object Set]': 'Set',
            '[object WeakMap]': 'WeakMap',
            '[object WeakSet]': 'WeakSet',
            '[object ArrayBuffer]': 'ArrayBuffer',
            '[object DataView]': 'DataView',
            '[object Int8Array]': 'Int8Array',
            '[object Uint8Array]': 'Uint8Array',
            '[object Uint8ClampedArray]': 'Uint8ClampedArray',
            '[object Int16Array]': 'Int16Array',
            '[object Uint16Array]': 'Uint16Array',
            '[object Int32Array]': 'Int32Array',
            '[object Uint32Array]': 'Uint32Array',
            '[object Float32Array]': 'Float32Array',
            '[object Float64Array]': 'Float64Array'
        };
    }
    
    demonstrateToStringDetection() {
        const testValues = [
            {},
            [],
            () => {},
            new Date(),
            /regex/,
            new Error(),
            Promise.resolve(),
            new Map(),
            new Set(),
            new WeakMap(),
            new WeakSet(),
            new ArrayBuffer(8),
            new Int8Array(4),
            null,
            undefined,
            42,
            'string',
            true,
            Symbol('test'),
            123n
        ];
        
        return testValues.map(value => {
            const toStringResult = Object.prototype.toString.call(value);
            const type = this.standardTags[toStringResult] || '未知类型';
            
            return {
                value: this.formatValue(value),
                toString: toStringResult,
                type,
                accurate: toStringResult !== '[object Object]' || 
                         (value !== null && typeof value === 'object' && 
                          Object.getPrototypeOf(value) === Object.prototype)
            };
        });
    }
    
    formatValue(value) {
        if (value === null) return 'null';
        if (value === undefined) return 'undefined';
        if (typeof value === 'function') return 'function() {}';
        if (typeof value === 'symbol') return value.toString();
        if (typeof value === 'bigint') return `${value}n`;
        return value;
    }
    
    // 基于 toString 的类型检测工具
    createToStringBasedChecker() {
        class ToStringTypeChecker {
            static getType(value) {
                const toString = Object.prototype.toString.call(value);
                return toString.slice(8, -1).toLowerCase();
            }
            
            static isObject(value) {
                if (value == null) return false;
                const type = this.getType(value);
                return type === 'object';
            }
            
            static isPlainObject(value) {
                if (!this.isObject(value)) return false;
                
                const proto = Object.getPrototypeOf(value);
                if (proto === null) return true;
                
                let constructor = proto.constructor;
                return typeof constructor === 'function' && 
                       constructor instanceof constructor && 
                       Object.prototype.toString.call(constructor.prototype) === '[object Object]';
            }
            
            static isArray(value) {
                return this.getType(value) === 'array';
            }
            
            static isFunction(value) {
                return this.getType(value) === 'function';
            }
            
            static isDate(value) {
                return this.getType(value) === 'date';
            }
            
            static isRegExp(value) {
                return this.getType(value) === 'regexp';
            }
            
            // 检查所有对象类型(包括内置对象)
            static isObjectLike(value) {
                return typeof value === 'object' && value !== null;
            }
        }
        
        return ToStringTypeChecker;
    }
}

constructor 属性检测

// constructor 属性检测分析
class ConstructorAnalysis {
    constructor() {
        this.constructorBehaviors = {
            reliability: 'constructor属性可被修改,不可靠',
            inheritance: '继承链中的constructor指向',
            builtinObjects: '内置对象的constructor行为'
        };
    }
    
    demonstrateConstructorIssues() {
        // 基础用例
        const obj = {};
        const arr = [];
        
        const baseCases = [
            { value: obj, constructor: obj.constructor, expected: Object },
            { value: arr, constructor: arr.constructor, expected: Array },
            { value: new Date(), constructor: new Date().constructor, expected: Date }
        ];
        
        // 篡改用例
        function CustomClass() {}
        const instance = new CustomClass();
        instance.constructor = Array; // 篡改constructor
        
        const tamperedCases = [
            { 
                value: instance, 
                originalConstructor: CustomClass,
                tamperedConstructor: instance.constructor,
                reliable: false
            }
        ];
        
        // null prototype 用例
        const nullProtoObj = Object.create(null);
        const nullProtoCases = [
            {
                value: nullProtoObj,
                hasConstructor: 'constructor' in nullProtoObj,
                constructorValue: nullProtoObj.constructor,
                note: '无原型对象的constructor行为'
            }
        ];
        
        return { baseCases, tamperedCases, nullProtoCases };
    }
    
    // 安全的 constructor 检测
    createSafeConstructorChecker() {
        class SafeConstructorChecker {
            static getConstructor(value) {
                if (value == null) return null;
                
                // 通过原型获取constructor
                const proto = Object.getPrototypeOf(value);
                if (proto == null) return null;
                
                return proto.constructor;
            }
            
            static hasConstructor(value, constructor) {
                const actualConstructor = this.getConstructor(value);
                return actualConstructor === constructor;
            }
            
            static isObjectByConstructor(value) {
                return this.hasConstructor(value, Object);
            }
            
            static isArrayByConstructor(value) {
                return this.hasConstructor(value, Array);
            }
            
            // 综合检测:constructor + toString
            static isPlainObjectSafe(value) {
                if (value == null) return false;
                
                // toString 检查
                if (Object.prototype.toString.call(value) !== '[object Object]') {
                    return false;
                }
                
                // constructor 检查
                const constructor = this.getConstructor(value);
                if (constructor !== Object) {
                    return false;
                }
                
                // 原型检查
                const proto = Object.getPrototypeOf(value);
                return proto === null || proto === Object.prototype;
            }
        }
        
        return SafeConstructorChecker;
    }
}

高级检测方案

综合类型检测系统

// 企业级类型检测系统
class EnterpriseTypeDetection {
    constructor() {
        this.detectionStrategies = new Map();
        this.cache = new WeakMap();
        this.performanceMonitor = new DetectionPerformanceMonitor();
        this.init();
    }
    
    init() {
        this.registerDetectionStrategies();
        this.setupPerformanceOptimizations();
    }
    
    registerDetectionStrategies() {
        // 策略1: 基础类型检测
        this.detectionStrategies.set('primitive', this.createPrimitiveDetection());
        
        // 策略2: 内置对象检测
        this.detectionStrategies.set('builtin', this.createBuiltinDetection());
        
        // 策略3: 自定义对象检测
        this.detectionStrategies.set('custom', this.createCustomObjectDetection());
        
        // 策略4: 特殊边界情况处理
        this.detectionStrategies.set('edgeCases', this.createEdgeCaseDetection());
    }
    
    createPrimitiveDetection() {
        return {
            name: '基础类型检测',
            priority: 1, // 最高优先级
            check: (value) => {
                const type = typeof value;
                
                // 快速排除非对象类型
                if (type !== 'object' && type !== 'function') {
                    return {
                        isObject: false,
                        type: type,
                        confidence: 1.0
                    };
                }
                
                // null 的特殊处理
                if (value === null) {
                    return {
                        isObject: false,
                        type: 'null',
                        confidence: 1.0
                    };
                }
                
                return null; // 继续下一个策略
            }
        };
    }
    
    createBuiltinDetection() {
        return {
            name: '内置对象检测',
            priority: 2,
            check: (value) => {
                const toString = Object.prototype.toString.call(value);
                const typeTag = toString.slice(8, -1);
                
                const builtinTypes = {
                    'Object': 'plain-object',
                    'Array': 'array',
                    'Function': 'function',
                    'Date': 'date',
                    'RegExp': 'regexp',
                    'Error': 'error',
                    'Map': 'map',
                    'Set': 'set',
                    'WeakMap': 'weakmap',
                    'WeakSet': 'weakset',
                    'Promise': 'promise'
                };
                
                if (builtinTypes[typeTag]) {
                    return {
                        isObject: true,
                        type: builtinTypes[typeTag],
                        specificType: typeTag,
                        confidence: 0.95
                    };
                }
                
                // 处理 typed arrays 和其他内置对象
                if (typeTag.endsWith('Array') || 
                    typeTag.includes('ArrayBuffer') ||
                    typeTag.includes('DataView')) {
                    return {
                        isObject: true,
                        type: 'builtin-object',
                        specificType: typeTag,
                        confidence: 0.95
                    };
                }
                
                return null;
            }
        };
    }
    
    createCustomObjectDetection() {
        return {
            name: '自定义对象检测',
            priority: 3,
            check: (value) => {
                // 检查是否为普通对象
                if (this.isPlainObject(value)) {
                    return {
                        isObject: true,
                        type: 'plain-object',
                        confidence: 0.9
                    };
                }
                
                // 检查类实例
                if (this.isClassInstance(value)) {
                    return {
                        isObject: true,
                        type: 'class-instance',
                        className: value.constructor.name,
                        confidence: 0.85
                    };
                }
                
                // 检查对象字面量但修改过原型的对象
                if (this.isObjectLike(value)) {
                    return {
                        isObject: true,
                        type: 'object-like',
                        confidence: 0.8
                    };
                }
                
                return null;
            }
        };
    }
    
    createEdgeCaseDetection() {
        return {
            name: '边界情况处理',
            priority: 4, // 最低优先级
            check: (value) => {
                // 处理 Object.create(null)
                if (value && Object.getPrototypeOf(value) === null) {
                    return {
                        isObject: true,
                        type: 'null-prototype-object',
                        confidence: 1.0
                    };
                }
                
                // 处理包装对象
                if (this.isWrapperObject(value)) {
                    return {
                        isObject: true,
                        type: 'wrapper-object',
                        wrappedType: typeof value.valueOf(),
                        confidence: 0.9
                    };
                }
                
                // 处理代理对象
                if (this.isProxyObject(value)) {
                    return {
                        isObject: true,
                        type: 'proxy',
                        confidence: 0.7
                    };
                }
                
                // 默认情况
                return {
                    isObject: typeof value === 'object' && value !== null,
                    type: 'unknown',
                    confidence: 0.5
                };
            }
        };
    }
    
    // 核心检测方法
    detectType(value) {
        // 缓存检查
        if (this.cache.has(value)) {
            return this.cache.get(value);
        }
        
        const startTime = performance.now();
        
        // 按优先级执行检测策略
        const strategies = Array.from(this.detectionStrategies.values())
            .sort((a, b) => a.priority - b.priority);
        
        let result = null;
        
        for (const strategy of strategies) {
            result = strategy.check(value);
            if (result !== null) {
                break;
            }
        }
        
        const endTime = performance.now();
        
        // 记录性能数据
        this.performanceMonitor.recordDetection(
            value, 
            result, 
            endTime - startTime
        );
        
        // 缓存结果(仅缓存对象)
        if (value !== null && typeof value === 'object') {
            this.cache.set(value, result);
        }
        
        return result;
    }
    
    // 工具方法
    isPlainObject(value) {
        if (typeof value !== 'object' || value === null) {
            return false;
        }
        
        const proto = Object.getPrototypeOf(value);
        if (proto === null) {
            return true;
        }
        
        let constructor = proto.constructor;
        return typeof constructor === 'function' && 
               constructor instanceof constructor && 
               Object.prototype.toString.call(constructor.prototype) === '[object Object]';
    }
    
    isClassInstance(value) {
        if (typeof value !== 'object' || value === null) {
            return false;
        }
        
        const constructor = value.constructor;
        if (constructor === undefined || constructor === Object) {
            return false;
        }
        
        // 检查是否为自定义类
        try {
            return typeof constructor === 'function' && 
                   constructor.name !== '' && 
                   constructor.name !== 'Object' &&
                   value instanceof constructor;
        } catch (e) {
            return false;
        }
    }
    
    isObjectLike(value) {
        return typeof value === 'object' && value !== null;
    }
    
    isWrapperObject(value) {
        if (value == null) return false;
        
        const primitiveTypes = ['boolean', 'number', 'string'];
        const constructorName = value.constructor.name;
        
        return primitiveTypes.some(type => 
            constructorName === `${type.charAt(0).toUpperCase() + type.slice(1)}`
        ) && typeof value.valueOf() !== 'object';
    }
    
    isProxyObject(value) {
        if (value == null) return false;
        
        try {
            // 尝试检测代理对象
            return !!value.__isProxy || 
                   (typeof value === 'object' && 
                    Object.prototype.toString.call(value) === '[object Object]' &&
                    this.hasUnusualBehavior(value));
        } catch (e) {
            return false;
        }
    }
    
    hasUnusualBehavior(obj) {
        // 检查对象是否有异常行为(可能是代理)
        const descriptors = Object.getOwnPropertyDescriptors(obj);
        const hasTraps = Object.keys(descriptors).some(key => {
            const desc = descriptors[key];
            return desc.get || desc.set || !desc.writable || !desc.enumerable;
        });
        
        return hasTraps;
    }
    
    // 快捷方法
    isObject(value) {
        const detection = this.detectType(value);
        return detection.isObject;
    }
    
    getObjectType(value) {
        const detection = this.detectType(value);
        return detection.type;
    }
    
    isPlainObjectStrict(value) {
        const detection = this.detectType(value);
        return detection.isObject && detection.type === 'plain-object';
    }
}

性能监控与优化

// 检测性能监控系统
class DetectionPerformanceMonitor {
    constructor() {
        this.metrics = new Map();
        this.thresholds = {
            slowDetection: 1, // 1ms
            cacheHitRate: 0.8 // 80%
        };
    }
    
    recordDetection(value, result, duration) {
        const type = result.type;
        const isObject = result.isObject;
        
        if (!this.metrics.has(type)) {
            this.metrics.set(type, {
                count: 0,
                totalDuration: 0,
                averageDuration: 0,
                slowDetections: 0,
                cacheHits: 0,
                cacheMisses: 0
            });
        }
        
        const metric = this.metrics.get(type);
        metric.count++;
        metric.totalDuration += duration;
        metric.averageDuration = metric.totalDuration / metric.count;
        
        if (duration > this.thresholds.slowDetection) {
            metric.slowDetections++;
        }
        
        // 记录缓存统计
        // 在实际实现中需要从检测系统获取缓存状态
    }
    
    getPerformanceReport() {
        const report = {
            summary: this.calculateSummary(),
            byType: Object.fromEntries(this.metrics),
            recommendations: this.generateOptimizationSuggestions()
        };
        
        return report;
    }
    
    calculateSummary() {
        let totalDetections = 0;
        let totalDuration = 0;
        
        this.metrics.forEach(metric => {
            totalDetections += metric.count;
            totalDuration += metric.totalDuration;
        });
        
        const averageDuration = totalDuration / totalDetections;
        const slowDetectionRate = Array.from(this.metrics.values())
            .reduce((sum, metric) => sum + metric.slowDetections, 0) / totalDetections;
        
        return {
            totalDetections,
            averageDuration: Math.round(averageDuration * 1000) / 1000,
            slowDetectionRate: Math.round(slowDetectionRate * 100) / 100,
            uniqueTypes: this.metrics.size
        };
    }
    
    generateOptimizationSuggestions() {
        const suggestions = [];
        const summary = this.calculateSummary();
        
        if (summary.averageDuration > 0.5) {
            suggestions.push({
                type: 'performance',
                message: '检测平均耗时较高,建议优化检测策略顺序',
                priority: 'high'
            });
        }
        
        if (summary.slowDetectionRate > 0.1) {
            suggestions.push({
                type: 'performance', 
                message: '慢速检测比例较高,建议添加更多缓存',
                priority: 'medium'
            });
        }
        
        // 分析具体类型的性能
        this.metrics.forEach((metric, type) => {
            if (metric.averageDuration > 1) {
                suggestions.push({
                    type: 'specific',
                    message: `类型"${type}"检测较慢,考虑特殊优化`,
                    priority: 'medium'
                });
            }
        });
        
        return suggestions;
    }
}

企业级解决方案

类型检测工具库实现

// 完整的类型检测工具库
class TypeDetectionLibrary {
    constructor() {
        this.detectionEngine = new EnterpriseTypeDetection();
        this.validationRules = new Map();
        this.customTypes = new Map();
        this.init();
    }
    
    init() {
        this.registerBuiltinValidators();
        this.setupConfiguration();
    }
    
    registerBuiltinValidators() {
        // 基础类型验证器
        this.validationRules.set('any', () => true);
        this.validationRules.set('undefined', value => value === undefined);
        this.validationRules.set('null', value => value === null);
        this.validationRules.set('boolean', value => typeof value === 'boolean');
        this.validationRules.set('number', value => typeof value === 'number' && !isNaN(value));
        this.validationRules.set('string', value => typeof value === 'string');
        this.validationRules.set('symbol', value => typeof value === 'symbol');
        this.validationRules.set('bigint', value => typeof value === 'bigint');
        this.validationRules.set('function', value => typeof value === 'function');
        
        // 对象类型验证器
        this.validationRules.set('object', value => this.detectionEngine.isObject(value));
        this.validationRules.set('plain-object', value => this.detectionEngine.isPlainObjectStrict(value));
        this.validationRules.set('array', value => Array.isArray(value));
        this.validationRules.set('date', value => value instanceof Date);
        this.validationRules.set('regexp', value => value instanceof RegExp);
        this.validationRules.set('promise', value => value instanceof Promise);
        this.validationRules.set('map', value => value instanceof Map);
        this.validationRules.set('set', value => value instanceof Set);
        this.validationRules.set('weakmap', value => value instanceof WeakMap);
        this.validationRules.set('weakset', value => value instanceof WeakSet);
        
        // 复合验证器
        this.validationRules.set('object-like', value => 
            value !== null && typeof value === 'object'
        );
        
        this.validationRules.set('primitive', value => 
            value === null || 
            (typeof value !== 'object' && typeof value !== 'function')
        );
        
        this.validationRules.set('thenable', value => 
            value !== null && 
            typeof value === 'object' && 
            typeof value.then === 'function'
        );
    }
    
    // 核心API
    is(value, type) {
        const validator = this.validationRules.get(type);
        if (!validator) {
            throw new Error(`未知的类型: ${type}`);
        }
        
        return validator(value);
    }
    
    getType(value) {
        return this.detectionEngine.getObjectType(value);
    }
    
    validate(value, schema) {
        if (typeof schema === 'string') {
            return this.is(value, schema);
        }
        
        if (Array.isArray(schema)) {
            // 联合类型
            return schema.some(type => this.is(value, type));
        }
        
        if (typeof schema === 'function') {
            // 自定义验证函数
            return schema(value);
        }
        
        if (typeof schema === 'object') {
            // 复杂模式验证
            return this.validateComplexSchema(value, schema);
        }
        
        return false;
    }
    
    validateComplexSchema(value, schema) {
        if (schema.type) {
            if (!this.is(value, schema.type)) {
                return false;
            }
        }
        
        if (schema.properties && this.is(value, 'object')) {
            for (const [key, propSchema] of Object.entries(schema.properties)) {
                if (!this.validate(value[key], propSchema)) {
                    return false;
                }
            }
        }
        
        if (schema.items && this.is(value, 'array')) {
            for (const item of value) {
                if (!this.validate(item, schema.items)) {
                    return false;
                }
            }
        }
        
        return true;
    }
    
    // 自定义类型注册
    registerType(typeName, validator, options = {}) {
        if (this.validationRules.has(typeName)) {
            if (!options.override) {
                throw new Error(`类型 "${typeName}" 已存在`);
            }
        }
        
        this.validationRules.set(typeName, validator);
        this.customTypes.set(typeName, {
            validator,
            registeredAt: Date.now(),
            ...options
        });
    }
    
    // 类型断言
    assert(value, type, message) {
        if (!this.validate(value, type)) {
            const errorMessage = message || 
                `期望类型: ${type}, 实际类型: ${this.getType(value)}`;
            throw new TypeError(errorMessage);
        }
        return true;
    }
    
    // 类型转换尝试
    coerce(value, targetType) {
        const currentType = this.getType(value);
        
        if (currentType === targetType) {
            return value;
        }
        
        const coercionRules = {
            'string': {
                from: ['number', 'boolean', 'bigint'],
                convert: (val) => String(val)
            },
            'number': {
                from: ['string', 'boolean'],
                convert: (val) => {
                    const num = Number(val);
                    return isNaN(num) ? undefined : num;
                }
            },
            'boolean': {
                from: ['string', 'number'],
                convert: (val) => Boolean(val)
            }
        };
        
        const rule = coercionRules[targetType];
        if (rule && rule.from.includes(currentType)) {
            return rule.convert(value);
        }
        
        return undefined; // 无法转换
    }
    
    // 工具方法
    getValidationRules() {
        return Array.from(this.validationRules.keys());
    }
    
    getCustomTypes() {
        return Array.from(this.customTypes.keys());
    }
    
    // 性能分析
    getPerformanceReport() {
        return this.detectionEngine.performanceMonitor.getPerformanceReport();
    }
}

// 快捷的单例实例
const TypeChecker = new TypeDetectionLibrary();

// 常用快捷方法
const isObject = (value) => TypeChecker.is(value, 'object');
const isPlainObject = (value) => TypeChecker.is(value, 'plain-object');
const isArray = (value) => TypeChecker.is(value, 'array');
const isFunction = (value) => TypeChecker.is(value, 'function');
const isDate = (value) => TypeChecker.is(value, 'date');
const isRegExp = (value) => TypeChecker.is(value, 'regexp');

实际应用场景示例

// 实际业务场景中的类型检测应用
class TypeDetectionUseCases {
    constructor() {
        this.checker = TypeChecker;
    }
    
    demonstrateAPIParameterValidation() {
        // API 参数验证
        function validateUserAPI(data) {
            const schema = {
                type: 'object',
                properties: {
                    id: 'number',
                    name: 'string',
                    email: 'string',
                    age: { type: 'number', optional: true },
                    preferences: {
                        type: 'object',
                        properties: {
                            theme: 'string',
                            notifications: 'boolean'
                        }
                    },
                    tags: {
                        type: 'array',
                        items: 'string'
                    }
                }
            };
            
            return TypeChecker.validate(data, schema);
        }
        
        const validUser = {
            id: 1,
            name: 'John Doe',
            email: 'john@example.com',
            preferences: {
                theme: 'dark',
                notifications: true
            },
            tags: ['vip', 'early-adopter']
        };
        
        const invalidUser = {
            id: '1', // 应该是数字
            name: null, // 不能为null
            email: 'invalid-email'
        };
        
        return {
            valid: validateUserAPI(validUser),
            invalid: validateUserAPI(invalidUser)
        };
    }
    
    demonstrateFormDataProcessing() {
        // 表单数据处理
        function processFormData(formData) {
            // 确保输入是对象
            TypeChecker.assert(formData, 'object', '表单数据必须是对象');
            
            const processed = {};
            
            for (const [key, value] of Object.entries(formData)) {
                // 根据字段名推断类型并清理数据
                if (key.includes('date') || key.includes('time')) {
                    processed[key] = TypeChecker.coerce(value, 'date') || new Date(value);
                } else if (key.includes('count') || key.includes('amount')) {
                    processed[key] = TypeChecker.coerce(value, 'number') || 0;
                } else if (key === 'agreeToTerms') {
                    processed[key] = TypeChecker.coerce(value, 'boolean') || false;
                } else {
                    processed[key] = TypeChecker.coerce(value, 'string') || String(value);
                }
            }
            
            return processed;
        }
        
        const rawFormData = {
            username: 'john_doe',
            birthDate: '1990-01-01',
            loginCount: '15',
            agreeToTerms: 'true',
            metadata: { source: 'web' }
        };
        
        return processFormData(rawFormData);
    }
    
    demonstrateConfigurationValidation() {
        // 应用配置验证
        class AppConfigValidator {
            static validate(config) {
                const schema = {
                    type: 'object',
                    properties: {
                        api: {
                            type: 'object',
                            properties: {
                                baseURL: 'string',
                                timeout: 'number',
                                retries: 'number'
                            }
                        },
                        features: {
                            type: 'object',
                            properties: {
                                darkMode: 'boolean',
                                analytics: 'boolean',
                                notifications: 'boolean'
                            }
                        },
                        ui: {
                            type: 'object', 
                            properties: {
                                theme: 'string',
                                language: 'string',
                                fontSize: 'number'
                            }
                        }
                    }
                };
                
                if (!TypeChecker.validate(config, schema)) {
                    throw new Error('无效的应用配置');
                }
                
                // 额外业务规则验证
                this.validateBusinessRules(config);
                
                return true;
            }
            
            static validateBusinessRules(config) {
                if (config.api.timeout < 0) {
                    throw new Error('API超时时间不能为负数');
                }
                
                if (config.api.retries > 10) {
                    throw new Error('重试次数过多');
                }
                
                if (config.ui.fontSize < 12 || config.ui.fontSize > 24) {
                    throw new Error('字体大小超出允许范围');
                }
            }
        }
        
        const validConfig = {
            api: {
                baseURL: 'https://api.example.com',
                timeout: 30000,
                retries: 3
            },
            features: {
                darkMode: true,
                analytics: false,
                notifications: true
            },
            ui: {
                theme: 'dark',
                language: 'zh-CN',
                fontSize: 16
            }
        };
        
        return AppConfigValidator.validate(validConfig);
    }
}

总结:对象检测的最佳实践

检测方法选择指南

// 对象检测方法决策树
class ObjectDetectionDecisionTree {
    static getDetectionStrategy(value, requirements) {
        const strategies = {
            // 简单场景:基础类型检查
            simple: {
                condition: () => requirements.speed > requirements.accuracy,
                methods: ['typeof', 'instanceof'],
                recommendation: '性能优先,接受一定的误判'
            },
            
            // 标准场景:平衡准确性和性能
            standard: {
                condition: () => requirements.accuracy >= 0.9 && requirements.speed >= 0.5,
                methods: ['Object.prototype.toString', 'constructor检查'],
                recommendation: '平衡方案,适用于大多数业务场景'
            },
            
            // 严格场景:高准确性要求
            strict: {
                condition: () => requirements.accuracy > 0.95,
                methods: ['综合检测系统', '企业级检测库'],
                recommendation: '准确性优先,适用于关键业务逻辑'
            },
            
            // 特殊场景:边界情况处理
            edgeCases: {
                condition: () => requirements.handleEdgeCases,
                methods: ['原型链分析', '自定义验证逻辑'],
                recommendation: '处理Object.create(null)等特殊场景'
            }
        };
        
        return Object.values(strategies).find(strategy => 
            strategy.condition()
        ) || strategies.standard;
    }
    
    static demonstrateMethodSelection() {
        const scenarios = [
            {
                name: '表单字段验证',
                requirements: { speed: 0.8, accuracy: 0.7, handleEdgeCases: false },
                recommended: 'simple',
                methods: ['typeof', 'instanceof']
            },
            {
                name: 'API响应数据验证',
                requirements: { speed: 0.6, accuracy: 0.9, handleEdgeCases: true },
                recommended: 'standard', 
                methods: ['Object.prototype.toString', '综合检查']
            },
            {
                name: '安全敏感操作',
                requirements: { speed: 0.4, accuracy: 0.99, handleEdgeCases: true },
                recommended: 'strict',
                methods: ['企业级检测库', '多层验证']
            },
            {
                name: '框架核心逻辑',
                requirements: { speed: 0.7, accuracy: 0.95, handleEdgeCases: true },
                recommended: 'strict',
                methods: ['缓存检测', '性能优化方案']
            }
        ];
        
        return scenarios;
    }
}

性能与准确性权衡

检测方法 准确性 性能 适用场景 局限性
typeof 极高 基础类型快速判断 无法区分对象类型
instanceof 类实例检测 跨域问题,constructor可篡改
Object.prototype.toString 内置对象检测 自定义对象检测有限
综合检测系统 极高 中低 企业级应用 实现复杂,性能开销

最佳实践总结

  1. 根据场景选择方法:不要一味追求最高准确性
  2. 缓存检测结果:对相同对象避免重复检测
  3. 分层验证:先快速排除,再详细检测
  4. 错误处理:检测失败时要有降级方案
  5. 性能监控:持续监控检测性能并优化

企业级建议

  • 在基础库中使用严格检测确保稳定性
  • 在业务代码中使用适度检测平衡性能
  • 建立统一的类型检测规范
  • 对关键路径进行性能分析和优化

通过深入理解各种检测方法的原理和适用场景,我们可以根据具体需求选择最合适的方案,在准确性、性能和可维护性之间找到最佳平衡点。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐