Как я могу гарантировать, что каждый аргумент был передан конструктору в JS

#javascript #class #object #error-handling #constructor

Вопрос:

У меня есть следующие два класса, где Circle есть расширение Entity . Конструктор для Entity использует один аргумент, который должен быть объектом, чтобы разрешить настройку нового Entity . Из-за более специфического характера Circle я создал конструктор с конкретными аргументами , который я хочу сделать менее гибким. Вот объявления классов:

 class Entity {  constructor(e) {  //use the attributes in the passed object to create a new Entity.  this.x = e.x; //position  this.y = e.y;  this.vY = this.vX = 0; //velocity  this.aX = this.aY = 0; //acceleration   } } class Circle extends Entity {  constructor(x, y, r, color) {  super({"x":x,"y":y}); //create Entity with given position;  this.r = r;  this.color = color;  } }  

Я также написал функцию addEntity(entity) , которая определяется следующим образом:

 addEntity(e) {  var ent_properties = Object.keys(e);  if(e.type) { //create a specific predefined Entity type, if thats what you want!  switch(e.type) {  case "circle":  try {  this.entities.push(new Circle(e.x, e.y, e.r, e.color));  } catch (err) { console.error(err); }  break;  default:  console.error("Invalid Entity Type Created: ");  console.error(e);  }  }  }  

Очевидно, что здесь еще предстоит проделать большой объем работы и многое из контекста, который я упустил (что не совсем относится к рассматриваемому вопросу, но моя проблема, с которой я обращаюсь ко всем здесь, заключается в следующем:

Если бы я позвонил

 e.addEntity({  "type": "circle",  "x": x,  "y": y,  "r": 100,  "color": "black"  });  

Это создает допустимый объект с заполненными всеми соответствующими значениями. Однако, допустим , я забыл включить "r" или вместо того , чтобы писать "r" , я написал "radius" , что было бы лучшим способом уловить это? На данный момент это просто создает Circle с this.r = undefined .

Кроме того, каков наилучший способ убедиться, что объект, которому я даю addEntity , имеет все необходимые атрибуты, в зависимости от типа Entity , который я хочу создать? Я хочу иметь возможность добавлять БОЛЬШЕ типов, а также быть уверенным, что если бы я добавил эти типы, я мог бы выдать ошибку, если тип Entity не был определен правильно.

TL;DR: Как мне быстро проверить в своем коде, что конструктор был запущен с использованием всех необходимых аргументов?

Ответ №1:

Повторение массива требуемых свойств и последующая проверка hasOwnProperty будут работать…

 const requiredProps = ['type', 'x', 'y', 'r', 'color']; // ...  // Test the argument: if (requiredProps.some(prop =gt; !e.hasOwnProperty(prop))) {  throw new Error('Required prop not found'); }  

Или , возможно, есть baseProps для Entity , и дополнительные реквизиты для других подклассов:

 const baseRequiredProps = ['type', 'x', 'y', 'r'];  // ... class Entity {  constructor(e) {  const requiredProps = [...baseRequiredProps, ...(this.constructor.additionalRequiredProps || [])]  if (requiredProps.some(prop =gt; !e.hasOwnProperty(prop))) {  throw new Error('Required prop not found');  }  // ... class Circle extends Entity {  static additionalRequiredProps = ['color'];  

В более крупных приложениях я бы рекомендовал подходить к подобным проблемам, используя вместо этого TypeScript, чтобы заставить вызывающего предоставить аргументы нужного типа, не требуя какого-либо дополнительного кода времени выполнения. К этому действительно нужно немного привыкнуть, но это значительно облегчает ведение кода.

 class Entity {  x: number;  y: number;  constructor(e: Entity) {  this.x = e.x;  this.y = e.y;  } } // works: const e = new Entity({ x: 5, y: 10 });  class Circle extends Entity {  type = 'circle';  r: number;  color: string;  constructor(e: Circle) {  super(e);  this.type = e.type;  this.r = e.r;  this.color = e.color;  } } // fails: const c = new Circle({  x: 5,  y: 7,  radius: 12,  color: 'black',  type: 'circle' });  

Так radius как был случайно введен вместо r , вы получите сообщение об ошибке:

введите описание изображения здесь