Как я могу найти прототип класса компонента по имени класса в Angular и получить значение свойства, определенного в этом прототипе класса?

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 здесь. .


Изменить

I mentioned Angular because I want to learn if Angular has an internal method/property to find mapping of class properties metadata which allows me to access static properties of the class in router resolver method. Angular knows the route.component.name. So I thought it may have an internal place to find this kind of metadata.

// 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();


person Halil İbrahim Karaalp    schedule 13.11.2017    source источник
comment
Как вы думаете, почему он будет преобразован в AppSample1Component.prototype.propertyWithDefaultValue? typescriptlang.org/play/   -  person yurzui    schedule 13.11.2017
comment
зачем вам уже нужно устанавливать прототип встроенного класса? Расширьте его и установите свои пользовательские переменные в пользовательском дочернем классе.   -  person omeralper    schedule 13.11.2017
comment
@yurzui Именно этот синтаксис я использовал для доступа к свойству прототипа класса в javascript. Вот почему я написал это, чтобы показать в качестве примера. Не потому, что я думаю, что он должен трансформироваться в такую ​​форму.   -  person Halil İbrahim Karaalp    schedule 13.11.2017
comment
@omeralper Да, ты прав. Это просто для демонстрации проблемы. Я пытаюсь узнать, можно ли получить доступ к этому свойству, пока у меня просто есть имя класса компонента в строковой переменной.   -  person Halil İbrahim Karaalp    schedule 13.11.2017


Ответы (1)


Если я правильно понимаю ваш вопрос, вы спрашиваете: «Возможно ли динамическое разрешение класса с учетом его имени?»

Где вы пытаетесь вызвать этот код и находитесь ли вы в 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. Вам, конечно, нужно добавить все классы, с которыми вы можете столкнуться.

person ehrencrona    schedule 20.11.2017
comment
Спасибо за Ваш ответ. Я подготовил jsfiddle.net/hallilibrahim/wvm17c8d для расширенной версии вопроса. - person Halil İbrahim Karaalp; 21.11.2017