#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
, вы получите сообщение об ошибке: