Доступ к статическому методу nodejs с использованием строковой переменной

#javascript #node.js #class #variables

#javascript #node.js #класс #переменные

Вопрос:

Я импортировал несколько классов в Adonis

 const User = use('App/Models/User')
const Orders = use('App/Models/Orders')
  

Я хочу иметь возможность динамически обращаться к одному из вышеупомянутых классов. Под этим я подразумеваю, что переменная будет содержать класс, к которому я хочу получить доступ. Переменная будет заполнена с помощью вызова API от пользователя.

 let className = 'Orders'
  

Как использовать className переменную для доступа к классу Orders.

Я пытался

 [className].query().where('orderNumber','123').fetch()
  

Однако, похоже, это не работает.

Ответ №1:

Создайте name -> class карту:

 const classes = {
  __proto__: null, // to avoid people being able to pass something like `toString`
  Users,
  Orders,
};
// or if you don't want to use __proto__
const classes = Object.assign(
  Object.create(null),
  {Users, Orders}
);
  

и получить доступ к нужному классу с помощью classes[className] . Конечно, проверьте, существует ли класс или нет.


Я пытался

 [className].query().where('orderNumber','123').fetch()
  

Однако, похоже, это не работает.

В этом контексте, [...] обозначает литерал массива, поэтому [className] просто создает массив, содержащий className (который в вашем примере является строкой) в качестве единственного элемента.

Комментарии:

1. Небольшой обходной путь и простой объект для представления каждого возможного класса.

2. Да, сжатые свойства (или как там это называется) действительно хороши для этого.

3. Очень хорошо, спасибо. Я попробовал, и это работает. Я приму этот ответ.

4. @FelixKling Эта __proto__: null строка была чистым золотом.

5. Хотя я немного беспокоюсь. Большие красные поля для __proto__ вверху: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference /…

Ответ №2:

Вообще избегайте преобразования переменной в строку. Просто используйте:

 let className = Orders;
className.query().where('orderNumber','123').fetch()
  

Если класс создается с помощью вызова API, используйте простой оператор switch:

 let class;
switch (apiCall.name) {
    case 'orders':
        class = Orders;
        break;
    case 'users':
        class = Users;
        break;
    default:
        throw 'Invalid API Call';
}

class.query().where('orderNumber','123').fetch()
  

Комментарии:

1. Мне нужно получить доступ к классу динамически. Имя класса будет передано пользователем через вызов API.

2. Вы должны были упомянуть вызов API в своем первоначальном вопросе.

3. Я обновил вопрос, чтобы объяснить, что я подразумеваю под динамическим.

Ответ №3:

Проще всего было бы eval(className).query().where('orderNumber','123').fetch() , но если вы хотите проверить существование значений как реального класса, вам, вероятно, следует реализовать switch или if-else-if для проверки и присвоения className и вызова только в том случае, если оно действительно присутствует.

Комментарии:

1. При упоминании eval() вы также должны упомянуть, насколько это зло. Это создает множество дыр в безопасности и обычно приносит больше вреда, чем пользы. Я не могу с чистой совестью рекомендовать это решение.

2. Никогда eval пользовательский ввод.

3. @FrankerZ Я хотел добавить отказ от ответственности, но тогда я этого не сделал. 😀

4. Как вы его очищаете? Если вы не уверены на 100%, что очищаете все, что может выдать пользователь, то последующая обработка входных данных может быть очень опасной. Отказ от eval в совокупности устраняет многие проблемы безопасности.

5.Конечно, но если вы проверите, className является ли это существующим именем класса, вы также можете загрузить фактический класс, как это сделал FrankerZ, и поэтому в eval ¯_(ツ)_/¯ этом нет необходимости.