$ cnpm install proto
protoA prototype-based inheritance/class library that makes it easy to create objects and inheritance hierarchies without losing the power of javascript's prototype system.
proto plays nice - you can use proto to inherit from any object, even if it was created with a different inheritance library!instanceof works with proto classesundefined)!new operatorproto. proto properly* creates classes that inherit from native objects - even all the Error types. *Inheriting certain native javascript objects has some limitations (see below)prototype and constructor properties are propertly setproto doesn't use Object.create so it should work with older browsers ( testers welcome! )proto is small: (833 bytes minified and gzipped in UMD format)proto is lightweight. It doesn't attempt to emulate class-based languages or create any fancy features you probably don't actually need (interfaces, abstract classes, etc)var Person = proto(function() { // prototype builder
this.init = function(legs, arms) { // constructor
this.legs = legs
this.arms = arms
}
this.getCaughtInBearTrap = function() { // instance method
this.legs -= 1
}
this.limbs = function() {
return this.arms + this.legs
}
Object.defineProperty(this, 'limbs', { // getters (and setters, etc) can be set right on the prototype!
get: function() {
return this.arms + this.legs
}
})
})
var Girl = proto(Person, function() { // inheritance
this.haveBaby = function() {
return Person(2,2)
}
})
var g = Girl(2,2) // instantiation
g.getCaughtInBearTrap()
console.log("Girl has "+g.limbs+" limbs")
console.log(": (")
var newPerson = g.haveBaby()
console.log("New person has" +newPerson.limbs+" limbs : )")
npm install proto
Accessing proto:
// node.js
var proto = require('proto')
// amd
require.config({paths: {proto: '../generatedBuilds/proto.umd.js'}})
require(['proto'], function(proto) { /* your code */ })
// global variable
<script src="proto.umd.js"></script>
proto; // proto.umd.js can define proto globally if you really
// want to shun module-based design
Using proto:
var Parent = proto(function() {
this; // points to the prototype, so set methods and static properties on this
// the name property has an impact on how proto classes are displayed in dev tools
this.name = 'MyProto'; // set a name for your proto class
this.init = function(v) { // constructor
this; // inside methods, 'this' references the instance
if(v > 0) {
this.x = v // you can normally access the object with this inside methods
} else if(v !== undefined) {
return true // you can return non-object values
} else {
return proto.undefined // return undefined by using a special constructor return value
}
}
this.anythingElse = 5 // static properties can be accessed by the class and the instance
// getters and setters (enumerable makes it available statically too! Ie)
Object.defineProperty(this, 'moose', {
enumerable: true,
get: function() {
return 5
},
set: function() {
console.log("just kidding, i'm not setting anything!")
}
})
// private functions don't have access to the correct 'this', so pass it in
var privateFn = function(that, arg1, etc) {
that.x = arg1 + etc
}
this.doSomething = function() {
privateFn(this, this.x, 1)
}
})
Parent.name; // the name property can be accessed directly from the returned proto class object
// you can inherit from any object!
// the resulting object factory will generate instances inheriting from:
// [if you inherit from]
// [a function]: that function's prototype
// [anything else]: that object itself
var Child = proto(Parent, function(superclass) {
this.init = function() {
superclass.init.apply(this, arguments) // super-class method call
// superclass.prototype.someMethod.apply(this, arguments) // remember that you probably need to access superclass.prototype for parents that aren't proto objects
// superclass.apply(this, arguments) // also remember that parents that aren't proto objects probably won't have an init method, but are constructors themselves (note that this should't be done with proto objectsbecause its creates a new instance)
this.r = 10
}
// create static methods just like instance methods - you can access them from the constructor
this.staticMethod = function(x) {
return this.constructor(x+12) // uses its own constructor to create a Child object
}
})
var object = Child(1) // instantiation
object.doSomething() // method call (as usual)
var object2 = Child.staticMethod(1) // static method call
Child.parent === Parent; // the 'parent' property on the will point to the proto class's parent
Creating a custom Error object:
var CustomError = proto(Error, function(superclass) {
this.name = 'CustomError'
this.init = function(msg, properties) {
superclass.call(this, msg)
for(var n in properties) {
this[n] = properties[n]
}
}
})
protoError and other exception types doesn't automatically set a correct name property, so you need to set it as a static properly "manually".String can't use the toString method.Array doesn't work.RegExp doesn't work either (the results can't use the test or match methods).name, length, arguments, and caller.name on firefox.Browser testing
Chrome [x]
Firefox [x]
Safari [x]
IE11 [ ]
IE10 [ ]
IE9 [ ]
IE8 [ ]
Opera [ ]
performance improvements
Consider creating a Proto2 that focuses on further performance improvements:
Anything helps:
How to submit pull requests:
npm install at its rootproto from his pjs project.this.name in the class construction function - the function passed to proto)Released under the MIT license: http://opensource.org/licenses/MIT
Copyright 2013 - present © cnpmjs.org | Home |