为啥 enumerable: false 不会级联到 TypeScript 中的继承类?
Posted
技术标签:
【中文标题】为啥 enumerable: false 不会级联到 TypeScript 中的继承类?【英文标题】:Why does enumerable: false not cascade to inherited classes in TypeScript?为什么 enumerable: false 不会级联到 TypeScript 中的继承类? 【发布时间】:2018-12-14 06:56:12 【问题描述】:如果我使用 TypeScript 和下面的方法将属性标记为 @enumerable(false)
,则扩展此可枚举标记为 false 的父类的子类将具有该属性,但它将可从 this answer 获取。
export
declare global
function enumerable(value: boolean): any;
const _global = (global /* node */ || window /* browser */) as any;
/**
* @enumerable decorator that sets the enumerable property of a class field to false.
* @param value true|false
*/
_global.enumerable = function(value: boolean): any
return function (target: any, propertyKey: string)
let descriptor = Object.getOwnPropertyDescriptor(target, propertyKey) || ;
if (descriptor.enumerable != value)
descriptor.configurable = true;
descriptor.writable = true;
descriptor.enumerable = value;
Object.defineProperty(target, propertyKey, descriptor)
;
这是我的层次结构的样子:
class BaseObject
@enumerable(false)
public _metadata: any =
id: 'number',
name: 'string'
;
class ContainerObject extends BaseObject
// ...
class CanvasObject extends BaseObject
// ...
这是运行时描述符的值:
var canvas = new CanvasObject();
console.log('Metadata Descriptor: ');
console.log(Object.getOwnPropertyDescriptor(canvas, '_metadata'));
Metadata Descriptor:
value:
beanId: 'number',
name: 'string' ,
writable: true,
enumerable: true,
configurable: true
如何确保该属性在父类和所有后续继承类中为enumerable: false
?
【问题讨论】:
你必须自己做。 javascript 中的继承不涉及继承这些标志。 每个原型对象都是它自己独特的对象,并且那些对象属性API与原型没有任何特殊关系;它们适用于所有对象。 使用原型链,您无法使用getOwnPropertyDescriptor
使用子作为参数来获取属性描述符,因为该属性属于原型,而不是子对象。我错过了什么吗?
我可以阻止我的子类完全从父类继承 _metadata 对象吗?
对不起@J.Pichardo,我在代码中留下了一个错字。我正在获取canvas
的属性描述符。
【参考方案1】:
这是由于在类声明中对类原型应用了装饰器。由于_metadata
是实例属性(它被脱糖为constructor() this._metadata = ...
),enumerable
装饰器不会影响它。
这是一个enumerable
装饰器的示例,它可以应用于原型(通常是方法)和实例属性:
function enumerable(value: boolean)
return (target: any, prop: string, descriptor?: PropertyDescriptor) =>
if (descriptor)
// prototype property
descriptor.enumerable = value;
else
// instance property
let propSymbol = Symbol(prop);
Object.defineProperty(target, prop,
configurable: true,
enumerable: value,
get() return this[propSymbol] ,
set(value) this[propSymbol] = value
);
;
请注意,为了处理 _metadata = ...
属性初始化器,描述符应包含 set
访问器以捕获属性分配。
【讨论】:
好吧,我对此进行了测试,我认为它现在正在创建属性并正确地使其不可枚举,但它没有在对象中设置_metadata
的值并返回 undefined
对于dna._metadata
。
它应该按预期工作,stackblitz.com/edit/typescript-nam2ew。您可以看到 _metadata 存在并且在 Chrome 控制台输出(浅色)中不可枚举。
如何防止 TypeScript 将元数据分配脱糖到构造函数中?我在我的编译器选项中设置了target: "esnext"
,但它总是脱糖到构造函数中,然后分配似乎失败了。
我不知道 esnext 目标所涵盖的确切列表是什么,但我不希望类字段保持原样,因为它们本身不受支持。 “语法糖”意味着它在功能上与脱糖对应物相同。不管是什么问题,都不应该是由它引起的。在我发布的示例中,类字段显然在编译时与构造函数代码脱糖。
我将 _metadata
重命名为 metadata
并将我的目标从 esnext
更改为 es2017
并且它正在工作!非常感谢,我需要在本周末之前完成这项工作。以上是关于为啥 enumerable: false 不会级联到 TypeScript 中的继承类?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Enumerable 中的方法返回 Enumerator?
如何为属性创建 TypeScript @enumerable(false) 装饰器