ES7之元数据

元数据api存在于reflect-matadata包中,是es7特性之一,用来在对象之外存储它上面的相关元数据,其中Reflect命名空间以前就存在,元数据api只是将方法注册到Reflect命名空间上,Reflect.ts:

/*Reflect命名空间 */
namespace Reflect {

    /*存储数据结构,其实是个对象,而不是Map*/
    type HashMap<V> = Record<string, V>;
    /*类似Byuffer,本质上是个字节数组*/
    interface BufferLike {
        /*根据偏移获取字节 */
        [offset: number]: number;
        /*字节数组长度 */
        length: number;
    }
    /*generate函数结果迭代器 */
    type IteratorResult<T> = { value: T, done: false } | { value: never, done: true };
    /*迭代器接口 */
    interface Iterator<T> {
        next(value?: any): IteratorResult<T>;
        throw?(value: any): IteratorResult<T>;
        return?(value?: T): IteratorResult<T>;
    }
    /*可迭代对象接口,可以获取迭代器 */
    interface Iterable<T> {
        "@@iterator"(): Iterator<T>;
    }

    interface IterableIterator<T> extends Iterator<T> {
        "@@iterator"(): IterableIterator<T>;
    }
    /*Map接口 */
    interface Map<K, V> extends Iterable<[K, V]> {
        size: number;
        has(key: K): boolean;
        get(key: K): V;
        set(key: K, value?: V): this;
        delete(key: K): boolean;
        clear(): void;
        keys(): IterableIterator<K>;
        values(): IterableIterator<V>;
        entries(): IterableIterator<[K, V]>;
    }

    interface MapConstructor {
        new (): Map<any, any>;
        new <K, V>(): Map<K, V>;
        prototype: Map<any, any>;
    }

    interface Set<T> extends Iterable<T> {
        size: number;
        has(value: T): boolean;
        add(value: T): this;
        delete(value: T): boolean;
        clear(): void;
        keys(): IterableIterator<T>;
        values(): IterableIterator<T>;
        entries(): IterableIterator<[T, T]>;
    }

    interface SetConstructor {
        new (): Set<any>;
        new <T>(): Set<T>;
        prototype: Set<any>;
    }

    interface WeakMap<K, V> {
        clear(): void;
        delete(key: K): boolean;
        get(key: K): V;
        has(key: K): boolean;
        set(key: K, value?: V): WeakMap<K, V>;
    }
    /*WeakMap类接口 */
    interface WeakMapConstructor {
        new (): WeakMap<any, any>;
        new <K, V>(): WeakMap<K, V>;
        prototype: WeakMap<any, any>;
    }
    /*成员装饰器接口 */
    type MemberDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor?: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
    declare const Symbol: { iterator: symbol, toPrimitive: symbol };
    declare const Set: SetConstructor;
    declare const WeakMap: WeakMapConstructor;
    declare const Map: MapConstructor;
    declare const global: any;
    declare const crypto: Crypto;
    declare const msCrypto: Crypto;
    declare const process: any;

    /*对一个类对象应用一个类装饰器数组 */
    export declare function decorate(decorators: ClassDecorator[], target: Function): Function;
    /*对一个对象的成员应用属性装饰器或者方法装饰器数组,最后一个参数为属性描述符*/
    export declare function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes?: PropertyDescriptor | null): PropertyDescriptor | undefined;
    export declare function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes: PropertyDescriptor): PropertyDescriptor;
    /*装饰器工厂,可以返回类、方法装饰器 */
    export declare function metadata(metadataKey: any, metadataValue: any): { (target: Function): void; (target: any, propertyKey: string | symbol): void; };
    /*在一个目标对象上定义元数据键值对 */
    export declare function defineMetadata(metadataKey: any, metadataValue: any, target: any): void;
    /*在一个目标对象的指定属性上定义元数据键值对 */
    export declare function defineMetadata(metadataKey: any, metadataValue: any, target: any, propertyKey: string | symbol): void;
    /*指定目标对象或其原型链上是否有指定key的元数据 */
    export declare function hasMetadata(metadataKey: any, target: any): boolean;
    /*指定目标对象或其原型链上的指定属性上是否有指定key的元数据 */
    export declare function hasMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean;
    /*目标本身不包含其原型链上是否有指定key的元数据 */ 
    export declare function hasOwnMetadata(metadataKey: any, target: any): boolean;
    /*指定目标对象不包含其原型链上的指定属性上是否有指定key的元数据 */
    export declare function hasOwnMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean;
    /*在目标对象或其原型链上查找指定key的元数据 */
    export declare function getMetadata(metadataKey: any, target: any): any;
    /*在目标对象或其原型链上查找指定属性上指定key的元数据 */
    export declare function getMetadata(metadataKey: any, target: any, propertyKey: string | symbol): any;
    /*在目标对象本身上查找指定key的元数据 */
    export declare function getOwnMetadata(metadataKey: any, target: any): any;
    /*在目标对象本身的指定属性下查找指定key的元数据 */
    export declare function getOwnMetadata(metadataKey: any, target: any, propertyKey: string | symbol): any;
    /*获取目标对象或其原型链上所有的元数据key */
    export declare function getMetadataKeys(target: any): any[];
    /*获取目标对象或其原型链上指定属性上所有的元数据key */
    export declare function getMetadataKeys(target: any, propertyKey: string | symbol): any[];
    /*获取目标对象本身所有的元数据key */
    export declare function getOwnMetadataKeys(target: any): any[];
    /*获取目标对象本身指定属性上所有的元数据key */
    export declare function getOwnMetadataKeys(target: any, propertyKey: string | symbol): any[];
    /*删除目标对象上指定key的元数据 */
    export declare function deleteMetadata(metadataKey: any, target: any): boolean;
    /*删除目标对象上指定属性指定key的元数据 */
    export declare function deleteMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean;
    /*匿名函数 */
    (function (this: any, factory: (exporter: <K extends keyof typeof Reflect>(key: K, value: typeof Reflect[K]) => void) => void) {
        /*获取全局对象 */
        const root = typeof global === "object" ? global :
            typeof self === "object" ? self :
            typeof this === "object" ? this :
            Function("return this;")();
        /*获取在Reflect命名空间上定义方法的方法 */
        let exporter = makeExporter(Reflect);
        /*如果全局上没有Reflect,添加到全局 */
        if (typeof root.Reflect === "undefined") {
            root.Reflect = Reflect;
        }
        /*全局已经有了,为Reflect定义方法 */
        else {
            exporter = makeExporter(root.Reflect, exporter);
        }

        factory(exporter);
        /*获取一个在Reflect上定义方法的方法 */
        function makeExporter(target: typeof Reflect, previous?: <K extends keyof typeof Reflect>(key: K, value: typeof Reflect[K]) => void) {
            /*返回那个方法吗,方法的参数为key、value */
            return <K extends keyof typeof Reflect>(key: K, value: typeof Reflect[K]) => {
                /*如果指定key的对象已经存在 */
                if (typeof target[key] !== "function") {
                    /*定义描述符 */
                    Object.defineProperty(target, key, { configurable: true, writable: true, value });
                }
                /*运行之前的定义方法 */
                if (previous) previous(key, value);
            };
        }
    })
    (function (exporter) {
        /*对象上自有属性 */
        const hasOwn = Object.prototype.hasOwnProperty;
        /*是否支持Symbol*/
        const supportsSymbol = typeof Symbol === "function";
        /*Symbol.toPrimitive方法  */
        const toPrimitiveSymbol = supportsSymbol && typeof Symbol.toPrimitive !== "undefined" ? Symbol.toPrimitive : "@@toPrimitive";
        /*Symbol.iterator方法 */
        const iteratorSymbol = supportsSymbol && typeof Symbol.iterator !== "undefined" ? Symbol.iterator : "@@iterator";
        /*智斗支持Object.create方法 */
        const supportsCreate = typeof Object.create === "function";
        /*是否支持_proto_属性 */
        const supportsProto = { __proto__: [] } instanceof Array; 
        /*不支持create与_proto_ */
        const downLevel = !supportsCreate && !supportsProto;
        const HashMap = {
            create: supportsCreate
                ? <V>() => MakeDictionary(Object.create(null) as HashMap<V>)
                : supportsProto
                    ? <V>() => MakeDictionary({ __proto__: null as any } as HashMap<V>)
                    : <V>() => MakeDictionary({} as HashMap<V>),
            has: downLevel
                ? <V>(map: HashMap<V>, key: string | number | symbol) => hasOwn.call(map, key)
                : <V>(map: HashMap<V>, key: string | number | symbol) => key in map,
            get: downLevel
                ? <V>(map: HashMap<V>, key: string | number | symbol): V | undefined => hasOwn.call(map, key) ? map[key] : undefined
                : <V>(map: HashMap<V>, key: string | number | symbol): V | undefined => map[key],
        };
        /*是否支持原型 */
        const functionPrototype = Object.getPrototypeOf(Function);
        /*环境变量 */
        const usePolyfill = typeof process === "object" && process.env && process.env["REFLECT_METADATA_USE_MAP_POLYFILL"] === "true";
        const _Map: typeof Map = !usePolyfill && typeof Map === "function" && typeof Map.prototype.entries === "function" ? Map : CreateMapPolyfill();
        const _Set: typeof Set = !usePolyfill && typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : CreateSetPolyfill();
        const _WeakMap: typeof WeakMap = !usePolyfill && typeof WeakMap === "function" ? WeakMap : CreateWeakMapPolyfill();

        /*元数据内部存储Map,为一个三级Map
          第一级key为target对象,value为存储在这个target上的所有属性上的元数据
          第二级key为属性值,如果直接在target对象上定义,属性值为空字符串,value为元数据键值对
          第三级key为元数据键,value为元数据值
          其中只有target上的属性值为字符串、symbol,其它都可以为任何类型  
        */
        const Metadata = new _WeakMap<any, Map<string | symbol | undefined, Map<any, any>>>();
        /*为target应用装饰器的方法重载 */
        function decorate(decorators: ClassDecorator[], target: Function): Function;
        function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes?: PropertyDescriptor | null): PropertyDescriptor | undefined;
        function decorate(decorators: (PropertyDecorator | MethodDecorator)[], target: any, propertyKey: string | symbol, attributes: PropertyDescriptor): PropertyDescriptor;
        /*方法实现 */
        function decorate(decorators: (ClassDecorator | MemberDecorator)[], target: any, propertyKey?: string | symbol, attributes?: PropertyDescriptor | null): PropertyDescriptor | Function | undefined {
            /*属性值存在,则说明装饰器为成员装饰器或方法装饰器 */
            if (!IsUndefined(propertyKey)) {
                if (!IsArray(decorators)) throw new TypeError();
                if (!IsObject(target)) throw new TypeError();
                if (!IsObject(attributes) && !IsUndefined(attributes) && !IsNull(attributes)) throw new TypeError();
                if (IsNull(attributes)) attributes = undefined;
                /*转化属性值 */
                propertyKey = ToPropertyKey(propertyKey);
                /*装饰指定属性*/
                return DecorateProperty(<MemberDecorator[]>decorators, target, propertyKey, attributes);
            }
            /*属性值不存在,则说明装饰器为类装饰器 */
            else {
                if (!IsArray(decorators)) throw new TypeError();
                if (!IsConstructor(target)) throw new TypeError();
                /*装饰类 */
                return DecorateConstructor(<ClassDecorator[]>decorators, <Function>target);
            }
        }
        /*将方法定义在命名空间Reflect上 */
        exporter("decorate", decorate);
        /*方法或类装饰器工厂 */
        function metadata(metadataKey: any, metadataValue: any) {
            /*装饰器方法重载 */
            function decorator(target: Function): void;
            function decorator(target: any, propertyKey: string | symbol): void;
            /*装饰器方法实现 */
            function decorator(target: any, propertyKey?: string | symbol): void {
                if (!IsObject(target)) throw new TypeError();
                if (!IsUndefined(propertyKey) && !IsPropertyKey(propertyKey)) throw new TypeError();
                /*在对象本身的属性(如果存在)上定义元数据*/
                OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey);
            }
            /*返回装饰器方法 */
            return decorator;
        }
        exporter("metadata", metadata);

        /*定义元数据方法重载 */
        function defineMetadata(metadataKey: any, metadataValue: any, target: any): void;
        function defineMetadata(metadataKey: any, metadataValue: any, target: any, propertyKey: string | symbol): void;
        /*定义元数据方法实现 */
        function defineMetadata(metadataKey: any, metadataValue: any, target: any, propertyKey?: string | symbol): void {
            if (!IsObject(target)) throw new TypeError();
            if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey);
            /*定义元数据 */
            return OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey);
        }
        exporter("defineMetadata", defineMetadata);

        /*元数据是否存在对象或其原型链上 */
        function hasMetadata(metadataKey: any, target: any): boolean;
        function hasMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean;
        function hasMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean {
            if (!IsObject(target)) throw new TypeError();
            if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey);
            return OrdinaryHasMetadata(metadataKey, target, propertyKey);
        }
        exporter("hasMetadata", hasMetadata);

        /*元数据是否存在对象本身上 */
        function hasOwnMetadata(metadataKey: any, target: any): boolean;
        function hasOwnMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean;
        function hasOwnMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean {
            if (!IsObject(target)) throw new TypeError();
            if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey);
            return OrdinaryHasOwnMetadata(metadataKey, target, propertyKey);
        }
        exporter("hasOwnMetadata", hasOwnMetadata);

        /*从对象或其原型链上获取元数据方法 */
        function getMetadata(metadataKey: any, target: any): any;
        function getMetadata(metadataKey: any, target: any, propertyKey: string | symbol): any;
        function getMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): any {
            if (!IsObject(target)) throw new TypeError();
            if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey);
            return OrdinaryGetMetadata(metadataKey, target, propertyKey);
        }
        exporter("getMetadata", getMetadata);

        /*从对象本身获取元数据方法 */
        function getOwnMetadata(metadataKey: any, target: any): any;
        function getOwnMetadata(metadataKey: any, target: any, propertyKey: string | symbol): any;
        function getOwnMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): any {
            if (!IsObject(target)) throw new TypeError();
            if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey);
            return OrdinaryGetOwnMetadata(metadataKey, target, propertyKey);
        }
        exporter("getOwnMetadata", getOwnMetadata);

        /*获取对象或其原型链上所有元数据key的方法 */
        function getMetadataKeys(target: any): any[];
        function getMetadataKeys(target: any, propertyKey: string | symbol): any[];
        function getMetadataKeys(target: any, propertyKey?: string | symbol): any[] {
            if (!IsObject(target)) throw new TypeError();
            if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey);
            return OrdinaryMetadataKeys(target, propertyKey);
        }
        exporter("getMetadataKeys", getMetadataKeys);

        /*获取对象本身上所有元数据key的方法 */
        function getOwnMetadataKeys(target: any): any[];
        function getOwnMetadataKeys(target: any, propertyKey: string | symbol): any[];
        function getOwnMetadataKeys(target: any, propertyKey?: string | symbol): any[] {
            if (!IsObject(target)) throw new TypeError();
            if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey);
            return OrdinaryOwnMetadataKeys(target, propertyKey);
        }
        exporter("getOwnMetadataKeys", getOwnMetadataKeys);

        /*删除指定元数据的方法 */
        function deleteMetadata(metadataKey: any, target: any): boolean;
        function deleteMetadata(metadataKey: any, target: any, propertyKey: string | symbol): boolean;
        function deleteMetadata(metadataKey: any, target: any, propertyKey?: string | symbol): boolean {
            if (!IsObject(target)) throw new TypeError();
            if (!IsUndefined(propertyKey)) propertyKey = ToPropertyKey(propertyKey);
            const metadataMap = GetOrCreateMetadataMap(target, propertyKey, /*Create*/ false);
            if (IsUndefined(metadataMap)) return false;
            if (!metadataMap.delete(metadataKey)) return false;
            if (metadataMap.size > 0) return true;
            const targetMetadata = Metadata.get(target);
            targetMetadata.delete(propertyKey);
            if (targetMetadata.size > 0) return true;
            Metadata.delete(target);
            return true;
        }
        exporter("deleteMetadata", deleteMetadata);

        /*使用类装饰器数组装饰指定对象的方法 */
        function DecorateConstructor(decorators: ClassDecorator[], target: Function): Function {
            /*遍历 */
            for (let i = decorators.length - 1; i >= 0; --i) {
                const decorator = decorators[i];
                /*执行 */
                const decorated = decorator(target);
                /*如果类装饰器返回了构造函数 */
                if (!IsUndefined(decorated) && !IsNull(decorated)) {
                    /*如果返回的不是构造函数,抛出错误 */
                    if (!IsConstructor(decorated)) throw new TypeError();
                    target = <Function>decorated;
                }
            }
            return target;
        }

        /*使用成员装饰器数组装饰target对象的指定propertykey的成员,最后一个参数是方法描述符 */
        function DecorateProperty(decorators: MemberDecorator[], target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor | undefined): PropertyDescriptor | undefined {
            /*遍历 */
            for (let i = decorators.length - 1; i >= 0; --i) {
                const decorator = decorators[i];
                /*执行装饰器 */
                const decorated = decorator(target, propertyKey, descriptor);
                if (!IsUndefined(decorated) && !IsNull(decorated)) {
                    if (!IsObject(decorated)) throw new TypeError();
                    descriptor = <PropertyDescriptor>decorated;
                }
            }
            return descriptor;
        }

        /*获取或者创建指定对象的二、三级Map
          第一个参数为对象,第二个参数为属性*/
        function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: true): Map<any, any>;
        function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: false): Map<any, any> | undefined;
        function GetOrCreateMetadataMap(O: any, P: string | symbol | undefined, Create: boolean): Map<any, any> | undefined {
            /*获取指定对象的二级Map,下面包含了所有属性以及属性上对应的元数据数组 */
            let targetMetadata = Metadata.get(O);
            /*如果不存在 */
            if (IsUndefined(targetMetadata)) {
                if (!Create) return undefined;
                /*创建并设置新的Map */
                targetMetadata = new _Map<string | symbol | undefined, Map<any, any>>();
                Metadata.set(O, targetMetadata);
            }
            /*获取指定对象上指定属性P的三级Map,里面直接存储元数据*/
            let metadataMap = targetMetadata.get(P);
            /*如果不存在 */
            if (IsUndefined(metadataMap)) {
                if (!Create) return undefined;
                /*新建并设置三级Map */
                metadataMap = new _Map<any, any>();
                targetMetadata.set(P, metadataMap);
            }
            return metadataMap;
        }

        /*对象或其原型链上是否包含指定元数据 */
        function OrdinaryHasMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): boolean {
            /*对象本身是否包含指定元数据 */
            const hasOwn = OrdinaryHasOwnMetadata(MetadataKey, O, P);
            /*包含直接返回 */
            if (hasOwn) return true;
            /*获取对象原型 */
            const parent = OrdinaryGetPrototypeOf(O);
            /*从原型获取,递归过程,先查找原型对象本身,再查找原型的原型 */
            if (!IsNull(parent)) return OrdinaryHasMetadata(MetadataKey, parent, P);
            return false;
        }

        /*对象本身是否包含指定元数据 */
        function OrdinaryHasOwnMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): boolean {
            /*在不新建的情况下获取指定对象、指定属性的Map */
            const metadataMap = GetOrCreateMetadataMap(O, P,false);
            if (IsUndefined(metadataMap)) return false;
            return ToBoolean(metadataMap.has(MetadataKey));
        }

        /*从对象或其原型链上获取指定元数据 */
        function OrdinaryGetMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): any {
            /*对象本身获取指定元数据 */
            const hasOwn = OrdinaryHasOwnMetadata(MetadataKey, O, P);
            if (hasOwn) return OrdinaryGetOwnMetadata(MetadataKey, O, P);
            /*对象原型获取指定元数据,递归过程 */
            const parent = OrdinaryGetPrototypeOf(O);
            if (!IsNull(parent)) return OrdinaryGetMetadata(MetadataKey, parent, P);
            return undefined;
        }

        /*从对象本身获取元数据 */
        function OrdinaryGetOwnMetadata(MetadataKey: any, O: any, P: string | symbol | undefined): any {
            /*不新建的情况下获取指定对象、指定属性的元数据Map */
            const metadataMap = GetOrCreateMetadataMap(O, P,false);
            if (IsUndefined(metadataMap)) return undefined;
            return metadataMap.get(MetadataKey);
        }

        /*在对象上定义元数据 */
        function OrdinaryDefineOwnMetadata(MetadataKey: any, MetadataValue: any, O: any, P: string | symbol | undefined): void {
            /*在可新建的情况下获取指定对象、指定属性的元数据Map,并设置元数据 */
            const metadataMap = GetOrCreateMetadataMap(O, P,true);
            metadataMap.set(MetadataKey, MetadataValue);
        }

        /*从对象本身及其原型链上获取指定元数据key数组 */
        function OrdinaryMetadataKeys(O: any, P: string | symbol | undefined): any[] {
            /*获取对象本身上元数据key数组 */
            const ownKeys = OrdinaryOwnMetadataKeys(O, P);
            const parent = OrdinaryGetPrototypeOf(O);
            if (parent === null) return ownKeys;
            const parentKeys = OrdinaryMetadataKeys(parent, P);
            if (parentKeys.length <= 0) return ownKeys;
            if (ownKeys.length <= 0) return parentKeys;
            /*遍历去重 */
            const set = new _Set<any>();
            const keys: any[] = [];
            for (const key of ownKeys) {
                const hasKey = set.has(key);
                if (!hasKey) {
                    set.add(key);
                    keys.push(key);
                }
            }
            for (const key of parentKeys) {
                const hasKey = set.has(key);
                if (!hasKey) {
                    set.add(key);
                    keys.push(key);
                }
            }
            return keys;
        }

        /*获取对象本身的元数据key数组 */
        function OrdinaryOwnMetadataKeys(O: any, P: string | symbol | undefined): any[] {
            const keys: any[] = [];
            const metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false);
            if (IsUndefined(metadataMap)) return keys;
            const keysObj = metadataMap.keys();
            const iterator = GetIterator(keysObj);
            let k = 0;
            while (true) {
                const next = IteratorStep(iterator);
                if (!next) {
                    keys.length = k;
                    return keys;
                }
                const nextValue = IteratorValue(next);
                try {
                    keys[k] = nextValue;
                }
                catch (e) {
                    try {
                        IteratorClose(iterator);
                    }
                    finally {
                        throw e;
                    }
                }
                k++;
            }
        }
        /*检查指定对象的类型,返回枚举值 */
        function Type(x: any): Tag {
            if (x === null) return Tag.Null;
            switch (typeof x) {
                case "undefined": return Tag.Undefined;
                case "boolean": return Tag.Boolean;
                case "string": return Tag.String;
                case "symbol": return Tag.Symbol;
                case "number": return Tag.Number;
                case "object": return x === null ? Tag.Null : Tag.Object;
                default: return Tag.Object;
            }
        }
        /*对象类型枚举 */
        const enum Tag {Undefined,Null,Boolean,String,Symbol,Number,Object}
        /*是否是undefined*/
        function IsUndefined(x: any): x is undefined {
            return x === undefined;
        }
        /*null判断 */
        function IsNull(x: any): x is null {
            return x === null;
        }
        /*symbol判断*/ 
        function IsSymbol(x: any): x is symbol {
            return typeof x === "symbol";
        }
        /*对象判断 */
        function IsObject<T>(x: T | undefined | null | boolean | string | symbol | number): x is T {
            return typeof x === "object" ? x !== null : typeof x === "function";
        }
        /*转化输入为原始类型,一般用来转化对象属性,属性值只能为string、symbol、undefined之一*/
        function ToPrimitive(input: any, PreferredType?: Tag): undefined | null | boolean | string | symbol | number {
            /*非对象类型直接返回 */
            switch (Type(input)) {
                case Tag.Undefined: return input;
                case Tag.Null: return input;
                case Tag.Boolean: return input;
                case Tag.String: return input;
                case Tag.Symbol: return input;
                case Tag.Number: return input;
            }
            const hint: "string" | "number" | "default" = PreferredType === Tag.String ? "string" : PreferredType === Tag.Number ? "number" : "default";
            /*调用一个symbol方法 */
            const exoticToPrim = GetMethod(input, toPrimitiveSymbol);
            if (exoticToPrim !== undefined) {
                const result = exoticToPrim.call(input, hint);
                if (IsObject(result)) throw new TypeError();
                return result;
            }
            return OrdinaryToPrimitive(input, hint === "default" ? "number" : hint);
        }

        /*js原来的转化方法,调用对象的toString、valueOf方法 */
        function OrdinaryToPrimitive(O: any, hint: "string" | "number"): undefined | null | boolean | string | symbol | number {
            if (hint === "string") {
                const toString = O.toString;
                if (IsCallable(toString)) {
                    const result = toString.call(O);
                    if (!IsObject(result)) return result;
                }
                const valueOf = O.valueOf;
                if (IsCallable(valueOf)) {
                    const result = valueOf.call(O);
                    if (!IsObject(result)) return result;
                }
            }
            else {
                const valueOf = O.valueOf;
                if (IsCallable(valueOf)) {
                    const result = valueOf.call(O);
                    if (!IsObject(result)) return result;
                }
                const toString = O.toString;
                if (IsCallable(toString)) {
                    const result = toString.call(O);
                    if (!IsObject(result)) return result;
                }
            }
            throw new TypeError();
        }
        function ToBoolean(argument: any): boolean {
            return !!argument;
        }
        function ToString(argument: any): string {
            return "" + argument;
        }
        /*属性转换方法,属性值只能为string、symbol、undefined */
        function ToPropertyKey(argument: any): string | symbol {
            /*先转化为原始值 */
            const key = ToPrimitive(argument, Tag.String);
            /*symbol直接返回,其他类型转化为string */
            if (IsSymbol(key)) return key;
            /*其他类型转化为字符串,undefined当做字符串输出 */
            return ToString(key);
        }
以上就是元数据api的主要方法,重点是:

1.元数据存储为一个三级Map,三级的key分别为target对象、属性、元数据key

2.定义元数据方法存在两类:在某个对象的指定属性上定义,直接在对象上定义,此时属性为undefined,相应的键为undefined的字符串形式

3.获取元数据方法除了根据是否使用属性值分类外,还根据是否遍历原型链分类:直接从某个对象获取、从某个对象及其原型链获取

4.属性只能为string、symbol、undefined,当传入属性为对象时会进行转换,先转换为symbol、不行再转换为string

猜你喜欢

转载自blog.csdn.net/qq_27868061/article/details/79440129
ES7
今日推荐