Component = function (el, attrValue, id) {
  var self = this;

  // If component is sceneOnly check the entity is the scene element
  if (this.sceneOnly && !el.isScene) {
    throw new Error('Component `' + this.name + '` can only be applied to <a-scene>');
  }

  // If component name has an id we check component type multiplicity.
  if (id && !this.multiple) {
    throw new Error('Trying to initialize multiple ' + 'components of type `' + this.name + '`. There can only be one component of this type per entity.');
  }
  this.el = el;
  this.id = id;
  this.attrName = this.name + (id ? '__' + id : '');
  this.evtDetail = {
    id: this.id,
    name: this.name
  };
  this.initialized = false;
  this.el.components[this.attrName] = this;
  this.objectPool = objectPools[this.name];
  var events = this.events;
  this.events = {};
  eventsBind(this, events);

  // Allocate data and oldData.
  this.attrValue = undefined;
  if (this.isObjectBased) {
    this.data = this.objectPool.use();
    // Drop any properties added by dynamic schemas in previous use
    _utils_index_js__WEBPACK_IMPORTED_MODULE_3__.objectPool.removeUnusedKeys(this.data, this.schema);
    this.oldData = this.objectPool.use();
    _utils_index_js__WEBPACK_IMPORTED_MODULE_3__.objectPool.removeUnusedKeys(this.oldData, this.schema);
    this.attrValueProxy = new Proxy(this, attrValueProxyHandler);
  } else {
    this.data = undefined;
    this.oldData = undefined;
    this.attrValueProxy = undefined;
  }

  // Dynamic schema requires special handling of unknown properties to avoid false-positives.
  this.deferUnknownPropertyWarnings = !!this.updateSchema;

  // Last value passed to updateProperties.
  // This type of throttle ensures that when a burst of changes occurs, the final change to the
  // component always triggers an event (so a consumer of this event will end up reading the correct
  // final state, following a burst of changes).
  this.throttledEmitComponentChanged = _utils_index_js__WEBPACK_IMPORTED_MODULE_3__.throttleLeadingAndTrailing(function emitChange() {
    el.emit('componentchanged', self.evtDetail, false);
  }, 200);

  // Initial call to updateProperties, force clobber to trigger an initial computation of all properties.
  this.updateProperties(attrValue, true);
}
Component class definition.

Components configure appearance, modify behavior, or add functionality to
entities. The behavior and appearance of an entity can be changed at runtime
by adding, removing, or updating components. Entities do not share instances
of components.

@constructor
@param {object} el - Reference to the entity element.
@param {string} attrValue - Value of the corresponding HTML attribute.
@param {string} id - Optional id for differentiating multiple instances on the same entity.