autocreate
Advanced tools
Comparing version 1.0.0 to 1.1.0
(function() { | ||
var auto, copyProps, create, defProp, getDesc, named, | ||
var auto, copyProps, defProp, getDesc, mkAuto, named, | ||
hasProp = {}.hasOwnProperty; | ||
module.exports = auto = function(cons) { | ||
var cls, proto; | ||
proto = cons.prototype; | ||
return cls = copyProps(cons, named(cons, function() { | ||
return mkAuto(cons); | ||
}; | ||
mkAuto = function(cons, name, copier) { | ||
var cls, create; | ||
if (name == null) { | ||
name = cons.name; | ||
} | ||
if (copier == null) { | ||
copier = copyProps; | ||
} | ||
cls = copier(cons, named(name, cons, function() { | ||
var cc, inst, ret; | ||
if (this instanceof cls) { | ||
return cons.apply(this, arguments); | ||
} else if (cc = proto.__class_call__) { | ||
return cc.apply(proto, arguments); | ||
} else if (cc = cls.prototype.__class_call__) { | ||
return cc.apply(cls.prototype, arguments); | ||
} else { | ||
inst = create(proto); | ||
inst = new create(); | ||
ret = cons.apply(inst, arguments); | ||
@@ -24,11 +33,6 @@ if (Object(ret) === ret) { | ||
})); | ||
(create = function() {}).prototype = cls.prototype; | ||
return cls; | ||
}; | ||
create = function(proto) { | ||
create.prototype = proto; | ||
if (proto) { | ||
return new create(); | ||
} | ||
}; | ||
getDesc = Object.getOwnPropertyDescriptor; | ||
@@ -72,4 +76,22 @@ | ||
named = function(src, dst) { | ||
auto.subclass = function(name, base, props) { | ||
if (typeof name === "function") { | ||
props = base; | ||
base = name; | ||
name = base.name; | ||
} | ||
return mkAuto(base, name, function(src, dst) { | ||
dst.prototype = Object.create(base.prototype, props); | ||
dst.prototype.constructor = dst; | ||
dst.__proto__ = src; | ||
return dst; | ||
}); | ||
}; | ||
named = function(name, src, dst) { | ||
var args, body, i, j, len, prop, ref, ref1, results; | ||
src = { | ||
name: name, | ||
length: src.length | ||
}; | ||
ref = ['name', 'length']; | ||
@@ -91,3 +113,3 @@ for (i = 0, len = ref.length; i < len; i++) { | ||
} | ||
if (dst.name !== src.name || dst.length !== src.length) { | ||
if (dst.name !== name || dst.length !== src.length) { | ||
args = ""; | ||
@@ -102,3 +124,3 @@ if (src.length) { | ||
try { | ||
dst = new Function('$$' + src.name, body = ("return function NAME(" + args + ") {\n return $$NAME.apply(this, arguments);\n}").replace(/NAME/g, src.name))(dst); | ||
dst = new Function('$$' + name, body = ("return function NAME(" + args + ") {\n return $$NAME.apply(this, arguments);\n}").replace(/NAME/g, name))(dst); | ||
} catch (_error) {} | ||
@@ -105,0 +127,0 @@ } |
{ | ||
"name": "autocreate", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "`new`-less classes for ES7/Babel, TypeScript, CoffeeScript, etc.", | ||
@@ -35,2 +35,4 @@ "repository": "git@github.com:pjeby/autocreate.git", | ||
"mocha": "^2.2.5", | ||
"babel-core": "^5.8.21", | ||
"mockdown": "pjeby/mockdown", | ||
"chai": "^1.9.1", | ||
@@ -37,0 +39,0 @@ "sinon": "^1.9.1", |
@@ -5,3 +5,5 @@ # autocreate | ||
```javascript | ||
<!--mockdown-setup: languages.js = 'babel'; languages.babel.options.stage=0; --> | ||
```js | ||
auto = require('autocreate'); | ||
@@ -19,3 +21,3 @@ | ||
```javascript | ||
```js | ||
@auto class dualUse { | ||
@@ -59,3 +61,3 @@ constructor() { | ||
```javascript | ||
```js | ||
auto = require('autocreate'); | ||
@@ -96,3 +98,3 @@ | ||
// just do whatever needs doing. | ||
}); | ||
}; | ||
``` | ||
@@ -103,3 +105,3 @@ | ||
##### In TypeScript (or Babel w/ES7 features enabled) | ||
```javascript | ||
```js | ||
@auto class MyClass { | ||
@@ -135,3 +137,3 @@ constructor() { | ||
// This will run if `new MyClass()` is used | ||
}); | ||
}; | ||
@@ -197,3 +199,3 @@ MyClass.prototype.__class_call__ = function () { | ||
```javascript | ||
```js | ||
@auto class BaseClass { | ||
@@ -216,1 +218,26 @@ __class_call__() { | ||
This will then return a `Subclass` instance when you call `Subclass()` without `new`, but fall through to whatever special handling you've set up when you call `BaseClass()` without `new`. | ||
### Programmatic Subclass Creation | ||
As a convenience feature for metaprogramming, `autocreate` exposes a `.subclass(name?, base, props?)` utility function for creating ES6-style subclasses of `base` with the given `name` and descriptors (`props`). If `name` is null or omitted, the base class name is used. Static properties are inherited via `__proto__`: | ||
```js | ||
let sub = auto.subclass('sub', BaseClass, {foo: {value: "bar"}}); | ||
BaseClass.somethingStatic = 42; | ||
console.log(sub.name); | ||
console.log(sub.somethingStatic); | ||
console.log(sub().foo); | ||
console.log(sub() instanceof sub); | ||
console.log(sub() instanceof BaseClass); | ||
``` | ||
> sub | ||
> 42 | ||
> bar | ||
> true | ||
> true | ||
Note that this function doesn't allow you to change the base class's constructor behavior, though you can of course define a new `__class_call__` in the subclass's properties. It's mainly useful for creating ES5/ES6-style subclasses when your favorite language only does ES3-style inheritance. |
13848
119
236
10