A lightweight class system. It's just prototypes!
// adapted from coffeescript.org// P.js exposes the `P` variablevar Animal = Pthisname = name; ;console.logthisname+" moved "+meters+"m.";;var Snake = PAnimalconsole.log"Slithering...";animalmovecallthis 5;;;var Horse = PAnimalconsole.log"Galloping...";animalmovecallthis 45;;;var sam = Snake"Sammy the Python"tom = Horse"Tommy the Palomino";sammovetommove
Most class systems for JS let you define classes by passing an object. P.js lets you pass a function instead, which allows you to closure private methods and macros. It's also <0.4kb minified (
make report: 478).
- interfaces, abstract static factory factories, and other bloat
- use Object.create (it even works in IE < 8!)
- hack functions onto
- rely on magical object keys which don't minify (the only special name is
- inheritable constructors (via the optional
- closure-based "private" methods (see below)
- easily call
superon public methods without any dirty hacks
- instantiate your objects without calling the constructor (absolutely necessary for inheritance)
- construct objects with variable arguments
You can call
P in a few different ways:
// this defines a class that inherits directly from Object.P// define private methods as regular functions that take// `self` (or `me`, or `it`, or anything you really want)// ...myPrivateMethodthis 1 2;// you can also return an object from this function, which will// be merged into the prototype.return thing: 3 ;;// this defines a class that inherits from MySuperclassPMySuperclass// call superclass methods with super.method.call(this, ...)// or super.method.apply(this, arguments)superinitcallthis;;;// for shorthand, you can pass an object in lieu of the function argument,// but you lose the niceness of super and private methods.P thisthing = a ;MyClass = P console.log"init!" a b ; ;// instantiate objects by calling the class as a functionMyClass1 2 // => init!, 1, 2// to initialize with varargs, use `apply` like any other function.var argsList = 1 2;MyClassapplynull argsList // init!, 1, 2// you can use it like an idiomatic class:// `new` is optional, not really recommended.1 2 // => init!, 1, 2// non-pjs idiomatic subclassMyClasscallthis a a;3 // => init!, 3, 33 instanceof MyClass // => true// `new` may be used to "force" instantiation when ambiguous,// for example in a factory method that creates new instancesreturn a b;;// because without `new`, `this.constructor(a, b)` is equivalent to// `MyClass.call(this, a, b)` which as we saw in the previous example// mutates `this` rather than creating new instances// allocate uninitialized objects with .Bare// (much like Ruby's Class#allocate)// nothing loggedinstanceof MyClass // => true// you can use `.open` to reopen a class. This has the same behavior// as the regular definitions.// note that _super will still be set to the class's prototypeMyClass = P a: 1 ;var myInst = MyClass;MyClassopen protoa = 2 ;myInsta // => 2MyClassopen /* _super is Object.prototype here */ ;// you can also use `.extend(definition)` to create new subclasses. This is equivalent// to calling P with two arguments.var Subclass = MyClassextend a: 3 ;
Assuming you have it installed (via
npm install pjs), you can import it with
var P = require'pjs'P;
and go about your business.
from the root directory of the repo and
make will start working.
Here are the things you can build:
build/p.commonjs.js, which is the same but has
exports.P = Pat the end
build/p.amd.js, which is the same but has
define(P)at the end
make testruns the test suite using the commonjs version. Requires