<commit_before>/**
 * Abstract entity class
 * The createComponent function should be extended for the class to be usuable
 */
export default class AbstractEntity {
  constructor() {
    this.components = {};
  }

  /**
   * Creates a component instance and adds it to this entity
   *
   * @param {string} componentName the name of the component to add
   * @param {...mixed} args the arguments to pass to the component factory
   *
   * @returns {Object} self
   */
  add(componentName, ...args) {
    this.components[componentName] = this.constructor.createComponent(
      componentName,
      ...args
    );

    return this;
  }

  /**
   * Indicates whether the entity has the given component
   *
   * @param {string} componentName the component identifier
   * @returns {boolean} true if the entity has the component, otherwise false
   */
  has(componentName) {
    return typeof this.components[componentName] !== "undefined";
  }

  /**
   * Removes the component with the given name from this entity
   *
   * @param {string} componentName the component identifier
   * @returns {Object} self
   */
  remove(componentName) {
    this.components[componentName] = undefined;
    return this;
  }

  /**
   * Removes all the components from this entity
   */
  removeAll() {
    Object.keys(this.components).forEach(name => {
      this.remove(name);
    });

    return this;
  }

  /**
   * Returns an object containing all the entity's components indexed by name
   *
   * @returns {Object} object of components indexed by name
   */
  getComponents() {
    const components = {};
    Object.keys(this.components).forEach(name => {
      components[name] = this.components[name];
    });

    return components;
  }

  /**
   * Adds an accessor property to the class for accessing the given component,
   * i.e. component 'foo' is accessible on instances using entity.foo
   *
   * @param {string} name the name of the component
   */
  static defineComponent(name) {
    Object.defineProperty(this.prototype, name, {
      enumerable: true,
      configurable: true,
      get: function() {
        return this.components[name];
      },
      set: function(newValue) {
        this.components[name] = newValue;
      }
    });
  }

  /**
   * Abtract method. Returns a new component instance
   *
   * @param {string} name the name of the component
   * @param {...args} args arguments to pass to the component factory
   * @returns {mixed} component instance
   */
  static createComponent(name, ...args) {}
}<commit_msg>Minor optimisation with components<commit_after>// Prototype-less components object, improves performance
const Components = Object.create(null, {});

/**
 * Abstract entity class
 * The createComponent function should be extended for the class to be usuable
 */
export default class AbstractEntity {
  constructor() {
    this.components = Object.create(Components, {});
  }

  /**
   * Creates a component instance and adds it to this entity
   *
   * @param {string} componentName the name of the component to add
   * @param {...mixed} args the arguments to pass to the component factory
   *
   * @returns {Object} self
   */
  add(componentName, ...args) {
    this.components[componentName] = this.constructor.createComponent(
      componentName,
      ...args
    );

    return this;
  }

  /**
   * Indicates whether the entity has the given component
   *
   * @param {string} componentName the component identifier
   * @returns {boolean} true if the entity has the component, otherwise false
   */
  has(componentName) {
    return typeof this.components[componentName] !== "undefined";
  }

  /**
   * Removes the component with the given name from this entity
   *
   * @param {string} componentName the component identifier
   * @returns {Object} self
   */
  remove(componentName) {
    this.components[componentName] = undefined;
    return this;
  }

  /**
   * Removes all the components from this entity
   */
  removeAll() {
    Object.keys(this.components).forEach(name => {
      this.remove(name);
    });

    return this;
  }

  /**
   * Returns an object containing all the entity's components indexed by name
   *
   * @returns {Object} object of components indexed by name
   */
  getComponents() {
    const components = {};
    Object.keys(this.components).forEach(name => {
      components[name] = this.components[name];
    });

    return components;
  }

  /**
   * Adds an accessor property to the class for accessing the given component,
   * i.e. component 'foo' is accessible on instances using entity.foo
   *
   * @param {string} name the name of the component
   */
  static defineComponent(name) {
    Object.defineProperty(this.prototype, name, {
      enumerable: true,
      configurable: true,
      get: function() {
        return this.components[name];
      },
      set: function(newValue) {
        this.components[name] = newValue;
      }
    });
  }

  /**
   * Abtract method. Returns a new component instance
   *
   * @param {string} name the name of the component
   * @param {...args} args arguments to pass to the component factory
   * @returns {mixed} component instance
   */
  static createComponent(name, ...args) {} // eslint-disable-line
}
{'fraction_non_alphanumeric': 0.10785060975609756, 'fraction_numerical': 0.0, 'mean_word_length': 2.848240469208211, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3061069', 'n_tokens_mistral': 1460, 'n_tokens_neox': 1427, 'n_words': 481}