npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

create-class

v1.0.1

Published

Create classes, powerful features, no fluff.

Downloads

9

Readme

create-class

A simple approach to creating classes, support mixins, static methods, inheritance and property descriptors.

API

module.exports = createClass(description) -> Constructor

Create a constructor function where all properties of description will be copied to the prototype of the constructor. For example:

var assert = require('assert');

var Foot = createClass({
  numberOfToes: 5,
  tickle: function () {
    console.log('stop that!');
  }
});

var f = new Foot();

assert.equal(5, f.numberOfToes);

f.tickle(); //=> 'stop that!'

Prototype Properties

Each property of the class definition that isn't special name or a descriptor will be (shallow) copied to the prototype of the returned constructor. Descriptors are detected by checking if the property value is an object with a truthy isDescriptor property. For example this is how one could define a getter:

var Rect = createClass({
  constructor: function (width, height) {
    this.width = width;
    this.height = height;
  },

  area: {
    isDescriptor: true,
    get: function () { return this.width * this.height }
  }
});

The constructor property is special, and described further in the next section.

Special Properties

There are 4 special property names: constructor defines the constructor function that will be modified & returned, static defines properties that should be copied to the constructor function instead of it's prototype, include extends the constructor or it's prototype with an array of mixins, and inherit defines a parent class/constructor that this one should inherit from. All other property names are copied to the constructor prototype as described in prototype properties

constructor

The value of constructor should be a function that takes arguments and initializes this. Note that the constructor will be mutated, this isn't a problem for most classes where the constructor is written inline with the definition, but keep in mind that re-using the constructor function across multiple classes will have unexpected results.

static

The value of static should be an object whose properties you want to be copied onto the constructor function for the class. An example might be having a shared instance of a particular class:

var Pool = createClass({
  static: {
    defaultConfig: { host: 'localhost' }
    sharedInstance: null,
    getSharedInstance: function () {
      if (!this.sharedInstance) {
        this.sharedInstance = new this(this.defaultConfig);
      }
      return this.sharedInstance;
    },
  },

  constructor: function (config) {
    // 
  }
});

// elsewhere in your program:
var pool = Pool.getSharedInstance()

include

The value of include should be an array of mixins that you will augment this class. Two types of mixins are accepted: objects or functions. Function mixins are called with the constructor function for the class as their sole argument. The mixin function is then free to augment & modify the constructor (or it's prototype) however it sees fit:

var Foo = createClass({
  include: [
    function (Constructor) {
      Constructor.hello = 'world';
    }
  ]
});

assert.equal(Foo.hello, 'world');

The second type of mixin is an object, which will be treated exactly like a new class definition, except that the constructor property (if present) will be ignored. Mixins are applied in order, see construction order for more details.

inherit

The value of inherit should be another class/constructor function that you would like to serve as the prototype of this one. The inheritance will be set up using inherits. The super/parent class will be accessible via the super_ property of the constructor:

var Readable = require('streams').Readable;

var HelloStream = createClass({
  inherit: Readable,
  _read: function () {
    this.push('hello\n');
  }
});

var hellos = new HelloStream();
assert(hellos instanceof Readable);

Class construction algorithm

Calling createClass performs the following steps:

  1. Checks for the constructor property. If not defined, an empty constructor is created. This empty constructor will call the parent constructor if one is defined.
  2. Checks for the inherit property. If defined, the constructor function is made to inherit from the value of inherit: inherits(Constructor, definition.inherit)
  3. Applies the class definition as though it were a mixin to the constructor.

The process for applying mixins (defined in [apply-mixin.js][]) is:

  1. If mixin is a function, pass it the Constructor function.
  2. Else, if mixin is not an object, a TypeError will be thrown.
  3. If the mixin defines a static property, copy each property of mixin.static to the constructor using setProperty.
  4. If the mixin defines an include property, apply each of the mixins in that array to the constructor in order. (Thus recursing back to step 1 for each mixin).
  5. If the mixin was a function, stop.
  6. Otherwise, copy each property of the mixin to the constructor prototype using setProperty.

Finally, the definition of setProperty is trivial:

function setProperty (target, name, value) {
  if (typeof value === 'object' && value.isDescriptor) {
    Object.defineProperty(target, name, value);
  } else {
    target[name] = value;
  }
}

License

MIT