2
export class AppSample1Component {
  public propertyWithDefaultValue = 'Lorem ipsum dolor sit amet!';
}

是否可以在 Angular 中访问组件的类原型?

例如(这个没有返回值):

console.log(AppSample1Component.prototype.propertyWithDefaultValue);

如果可能的话,如何在路由解析器函数中加入类的原型?

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | Promise<any> | any {
    const componentType = typeof route.component === 'string' ? route.component : route.component.name;
    console.log('Class name of the component: ', componentType);
    console.log('>>> I want to find the prototype of component class from ActivatedRouteSnapshot and get the value of "propertyWithDefaultValue" property of that class prototype in this section.');

    return new Promise((resolve, reject) => {
        Promise.all([
            this.getData()
        ]).then(
            () => {
                // Init component(s) after prefetch data, etc...
                resolve();
            },
            reject
            );
    });
}

您可以在此处检查问题的 StackBlitz 重现


编辑

我提到 Angular 是因为我想了解 Angular 是否有一个内部方法/属性来查找类属性元数据的映射,它允许我在路由器解析器方法中访问类的静态属性。Angular 知道 route.component.name。所以我认为它可能有一个内部位置可以找到这种元数据。

// Here's an example which shows a minimal use of OOP in my recent javascript projects
const myLib = {
    apply: function (obj, config) {
        if (obj && config && typeof config === 'object')
            for (var p in config)
                obj[p] = config[p];
        return obj;
    },
    extend: function (sc, bc) {
        var Fn = function () {};
        Fn.prototype = bc.prototype;
        var scpb = sc.prototype;
        var scp = sc.prototype = new Fn();
        scp.constructor = sc;
        if (bc.prototype.constructor === Object.prototype.constructor)
            bc.prototype.constructor = bc;
        myLib.apply(scp, scpb);
        sc.superclass = bc.prototype;
    }
};
myLib.textField = function (config) {

};
myLib.textField.prototype = {
    type: 'text'
};

myLib.numberField = function (config) {
	myLib.numberField.superclass.constructor.call(this, config);
};
myLib.numberField.prototype = {
    type: 'number',
    min: 0,
    max: 9999
};
myLib.extend(myLib.numberField, myLib.textField);

const obj1 = new myLib.textField();
const obj2 = new myLib.numberField();

console.group('My old JS way');
console.log(obj1.type, obj2.type);
console.log(myLib.textField.prototype.max, myLib.numberField.prototype.max);
console.groupEnd();

// And here is a demonstration of typescript generated javascript.
// Compiled typescript code generates javascript class as something like below.
// Typescript places the properties to the beginning of the constructor, not to prototype.
// This is why it's not possible to access class prototype directly.
myLib.numberField2 = function () {
    this.type = 'number';
    this.min = 0;
    this.max = 9999;
    //constructor block begin
    //constructor block end
};
const obj3 = new myLib.numberField2();
console.group('Typescript compiled output demonstration');
console.log(obj3.max); // prints 9999

console.log(myLib.numberField2.prototype.max); 
// this prints "undefined" because max property doesn't exist before object creation
console.groupEnd();

4

1 回答 1

0

如果我正确理解您的问题,您是在问“是否可以动态解析给定名称的类?”

您尝试调用此代码的位置以及您是否使用 Angular 似乎与问题无关。

这个问题的一般答案是“不”。类/模块在您的应用程序中不一定具有唯一的名称。例如,您可以在导入它们时重命名它们(例如import { LongClassName as LCN } from "./long-class-name";)。并且可以有多个具有相同名称的类。

假设您已经导入了所有可能需要解析的类,或者正在当前模块中定义它们,您可以使用它eval(classNameToResolve).prototype来获取类原型。eval但是,出于安全和性能原因,强烈建议不要使用。而且它不适用于所有模块捆绑器,或者如果您缩小代码。

所以,简而言之,没有。考虑创建一个允许您进行所需查找的映射,例如

const ALL_MY_CLASSES = {
  ClassA: ClassA,
  ClassB: ClassB
}

然后,您将能够使用ALL_MY_CLASSES[classNameToResolve].prototype. 当然,您确实需要添加您可能遇到的所有类。

于 2017-11-20T13:45:27.313 回答