finalized mixout(..) api...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-05-06 19:27:34 +03:00
parent 58461b949a
commit 87414a8edb
3 changed files with 42 additions and 12 deletions

View File

@ -511,9 +511,16 @@ objects themselves, making them fully reusable.
### `mixout(..)` ### `mixout(..)`
Remove objects out of a prototype chain Remove the first occurrence of each object out of a prototype chain
``` ```
mixout(<base>, <object>, ..) mixout(<base>, <object>, ..)
mixout(<base>, 'first', <object>, ..)
-> <base>
```
Remove all occurrences of each object out of a prototype chain
```
mixout(<base>, 'all', <object>, ..)
-> <base> -> <base>
``` ```

View File

@ -284,37 +284,60 @@ function(root, ...objects){
// Mix-out sets of methods/props/attrs out of an object prototype chain... // Mix-out sets of methods/props/attrs out of an object prototype chain...
// //
// Mix-out first occurrence of each matching object...
// mixout(root, object, ..) // mixout(root, object, ..)
// mixout(root, 'first', object, ..)
// -> root // -> root
// //
// This is the opposite to mixin(..) // Mix-out all occurrences of each matching object...
// mixout(root, 'all', object, ..)
// -> root
// //
// XXX Q: should this drop all occurences (current) or just the first??? //
// XXX revise... // This will match an object to a mixin iff:
// - if they are identical or
// - attr count is the same and,
// - attr names are the same and,
// - attr values are identical.
//
// NOTE: this is the opposite to mixin(..)
var mixout = var mixout =
module.mixout = module.mixout =
function(root, ...objects){ function(root, ...objects){
var match = function(root, obj){ var all = objects[0] == 'all' ?
!!objects.shift()
: objects[0] == 'first' ?
!objects.shift()
// default...
: false
var _match = function(root, obj){
// identity...
if(root === obj){ if(root === obj){
return true } return true }
// attr count...
if(Object.keys(root).length != Object.keys(obj).length){ if(Object.keys(root).length != Object.keys(obj).length){
return false } return false }
// names and values...
var e = Object.entries(obj) var e = Object.entries(obj)
while(e.length > 0){ while(e.length > 0){
var [k, v] = e.pop() var [k, v] = e.pop()
if(!root.hasOwnProperty(k) || root[k] !== v){ if(!root.hasOwnProperty(k) || root[k] !== v){
return false } } return false } }
return true } return true }
var drop = function(obj){ var _drop = function(obj){
var cur = root var cur = root
while(cur.__proto__ != null){ var found = false
match(cur.__proto__, obj) while(cur.__proto__ != null
// continue iff ...
&& (all || !found)){
found = _match(cur.__proto__, obj)
found
&& (cur.__proto__ = cur.__proto__.__proto__) && (cur.__proto__ = cur.__proto__.__proto__)
cur = cur.__proto__ } cur = cur.__proto__ } }
return root }
// do the work... // do the work...
objects.map(drop) objects.map(_drop)
return root } return root }

View File

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