fix + minor refactoring...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-04-27 04:16:35 +03:00
parent e8ed996aba
commit 1c16cf1221
3 changed files with 71 additions and 21 deletions

View File

@ -204,15 +204,20 @@ sources(<object>, <name>, <callback>)
Get parent method Get parent method
``` ```
parent(<method>, <this>) parent(<method>, <this>)
parent(<method>, <name>, <this>)
-> <parent-method> -> <parent-method>
-> undefined
parent(<prototype>, <name>, <this>)
-> <parent-value>
-> undefined
``` ```
Get parent method and call it Get parent method and call it
``` ```
parentCall(<method>, <this>) parentCall(<method>, <this>)
parentCall(<method>, <name>, <this>) parentCall(<prototype>, <name>, <this>)
-> <result> -> <result>
-> undefined
``` ```

View File

@ -87,40 +87,81 @@ function(obj, name, callback){
return res } return res }
// Find the next parent method in the prototype chain. // Find the next parent attribute in the prototype chain.
// //
// Get parent attribute value...
// parent(<value>, <name>, <this>)
// -> <value>
// -> undefined
//
// Get parent method...
// parent(<meth>, <this>) // parent(<meth>, <this>)
// parent(<meth>, <name>, <this>)
// -> <meth> // -> <meth>
// -> undefined
//
//
// Example:
// var X = object.Constructor('X', {
// __proto__: Y.prototype,
//
// attr: 123,
//
// method: function(){
// // get attribute...
// var a = object.parent(X.prototype.attr, 'attr', this)
//
// // get method...
// var ret = object.parent(X.prototype.method, this).call(this, ...arguments)
//
// // ...
// }
// })
// //
// //
// NOTE: there are cases where method.name is not set, so a name can be
// passed explicitly.
// NOTE: this is super(..) replacement... // NOTE: this is super(..) replacement...
// NOTE: if method is root (no super method) this will return undefined. // NOTE: the two forms differ only in that in the first case a method
// NOTE: for // usually has a .name attribute so it is not always necessary to
// explicitly state a name...
// NOTE: there are cases where method.name is not set (e.g. anonymous
// function), so a name should be passed explicitly...
// NOTE: when passing a method it is recommended to pass an explicit
// reference to it relative to the constructor, i.e.
// Constructor.prototype.method, this will avoid relative resolution
// loops, for example, this.method deep in a chain will resolve to
// the first .method value visible from 'this', i.e. the top most
// value and not the value visible from that particular level...
var parent = var parent =
module.parent = module.parent =
function(method, name, that){ function(proto, name, that){
// special case: method...
if(arguments.length == 2){ if(arguments.length == 2){
that = name var method = proto
proto = that = name
name = method.name name = method.name
// skip until we get to the method...
while(proto.__proto__ && proto[name] !== method){
proto = proto.__proto__
}
} }
// find the current method in the prototype chain... // skip till next name occurrence...
while(!that.hasOwnProperty(name) || that[name] !== method){ while(proto.__proto__ && !proto.hasOwnProperty(name)){
that = that.__proto__ proto = proto.__proto__
} }
// return the next method... // get next value...
return that.__proto__[name] } return proto.__proto__[name] }
// Find the next parent method and call it... // Find the next parent method and call it...
// //
// parentCall(<meth>, <this>, ...) // parentCall(<meth>, <this>, ...)
// parentCall(<meth>, <name>, this>, ...) // parentCall(<proto>, <name>, this>, ...)
// -> <res> // -> <res>
// -> undefined
// //
// //
// This also gracefully handles the case when no higher level definition
// is found, i.e. the corresponding parent(..) call will return undefined.
//
// NOTE: this is just like parent(..) but will call the retrieved method, // NOTE: this is just like parent(..) but will call the retrieved method,
// essentially this is a shorthand to: // essentially this is a shorthand to:
// parent(method, name, this).call(this, ...) // parent(method, name, this).call(this, ...)
@ -129,10 +170,14 @@ function(method, name, that){
// NOTE: for more docs see parent(..) // NOTE: for more docs see parent(..)
var parentCall = var parentCall =
module.parentCall = module.parentCall =
function(method, name, that, ...args){ function(proto, name, that, ...args){
return typeof(name) == typeof('str') ? var [p, c] = typeof(name) == typeof('str') ?
parent(method, name, that).call(that, ...args) [ [proto, name, that], [...arguments].slice(2)]
: parent(method, name).call(name, ...[that, ...args]) } : [ [proto, name], [...arguments].slice(1)]
var meth = parent(...p)
return meth instanceof Function ?
meth.call(...c)
: undefined }

View File

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