added simple construction of callable instances...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-04-10 18:30:55 +03:00
parent 5113c0af7c
commit 499a3e0d8a
3 changed files with 87 additions and 6 deletions

View File

@ -82,6 +82,56 @@ var Item = object.Constructor('Item', {
``` ```
```javascript
// callable instance constructor...
var Action = object.Constructor('Action',
// the first argument is allways the external call context, like
// normal this, but here we have two contexts:
// - external -- where the instance was called from
// - internal -- the instance (this)
// NOTE: if the prototype is explicitly defined as a function then
// it is the user's responsibility to call .__call__(..) method
// (see below)
function(context, ...args){
// return the instance...
return this
})
var action = new Action()
action()
// a different way to do the above...
var Action2 = object.Constructor('Action2', {
// this is the same as the above but a bit more convenient as we do
// not need to use Object.assign(..) or object.mixinFlat(..) to define
// attributes and props...
// NOTE: this is not called if a user defines the prototype as a function
// (see above)
__call__: function(context, ...args){
return this
},
})
```
```javascript
// low level constructor...
var LowLevel = object.Constructor('LowLevel', {
// Low level instance constructor...
// NOTE: if this is defined the return value is used as the instance
// NOTE: this is run in the context of the .prototype rather than
// the instance...
// NOTE: this has priority over the callable protocols above, thus
// the user must take care of both the prototype as function and
// prototype.__call__(..)...
__new__: function(context, ...args){
return {}
},
})
```
## Components ## Components
@ -102,8 +152,8 @@ mixinFlat(<root>, <object>, ...)
``` ```
``` ```
makeConstructor(<name>, <prototype>) Constructor(<name>, <prototype>)
makeConstructor(<name>, <class-prototype>, <prototype>) Constructor(<name>, <class-prototype>, <prototype>)
-> <constructor> -> <constructor>
``` ```

View File

@ -219,6 +219,7 @@ function(root, ...objects){
// ...mainly for inheritance. // ...mainly for inheritance.
// ...would also be helpful in this case to call all the // ...would also be helpful in this case to call all the
// constructors in the chain // constructors in the chain
// XXX need a simple way to make a function constructor...
var Constructor = var Constructor =
module.Constructor = module.Constructor =
// shorthand... // shorthand...
@ -227,14 +228,44 @@ function Constructor(name, a, b){
var proto = b == null ? a : b var proto = b == null ? a : b
var cls_proto = b == null ? b : a var cls_proto = b == null ? b : a
// mirror doc from target to func...
var _mirror = function(func, target){
Object.defineProperty(func, 'toString', {
value: function(...args){
return target.toString(...args) },
enumerable: false,
})
return func }
var __new__ = function(base, ...args){
}
var _constructor = function Constructor(){ var _constructor = function Constructor(){
// NOTE: the following does the job of the 'new' operator but // NOTE: the following does the job of the 'new' operator but
// with one advantage, we can now pass arbitrary args // with one advantage, we can now pass arbitrary args
// in... // in...
// This is equivalent to: // This is equivalent to:
// return new _constructor(json) // return new _constructor(json)
var obj = _constructor.prototype.__new__ instanceof Function ? var obj =
_constructor.prototype.__new__({}, ...arguments) // prototype defines .__new__(..)...
_constructor.prototype.__new__ instanceof Function ?
_constructor.prototype.__new__(this, ...arguments)
// prototype is a function...
// NOTE: we need to isolate the .prototype from instances...
: _constructor.prototype instanceof Function ?
_mirror(
function(){
return _constructor.prototype.call(obj, this, ...arguments) },
_constructor.prototype)
// prototype defines .__call__(..)...
// NOTE: we need to isolate the .__call__ from instances...
: _constructor.prototype.__call__ instanceof Function ?
_mirror(
function(){
return _constructor.prototype.__call__.call(obj, this, ...arguments) },
_constructor.prototype.__call__)
// default object base...
: {} : {}
obj.__proto__ = _constructor.prototype obj.__proto__ = _constructor.prototype
@ -257,7 +288,7 @@ function Constructor(name, a, b){
.toString() .toString()
.replace(/Constructor/g, name)) .replace(/Constructor/g, name))
// set an informative .toString... // set an informative Constructor .toString(..)...
// NOTE: do this only if .toString(..) is not defined by user... // NOTE: do this only if .toString(..) is not defined by user...
;((cls_proto || {}).toString() == ({}).toString()) ;((cls_proto || {}).toString() == ({}).toString())
// XXX is this the right way to go or should we set this openly??? // XXX is this the right way to go or should we set this openly???

View File

@ -1,6 +1,6 @@
{ {
"name": "ig-object", "name": "ig-object",
"version": "2.0.0", "version": "2.1.0",
"description": "", "description": "",
"main": "object.js", "main": "object.js",
"scripts": { "scripts": {