元数据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