Enumerable.js



Array generics introduced from JavaScript1.6


  • reverse
  • indexOf
  • lastIndexOf
  • forEach
  • map
  • reduce
  • reduceRight
  • filter
  • isArray
  • every
  • some


methods have moved to global



            Array.forEach([1,2],
                function(val,i){
                  console.log(i+" : "+val);
                }
            );
            


But local context still remains



            [1,2].forEach(function(val,i){
                  console.log(i+" : "+val);
                }
            );
            


ES5 Reasons

  • memory save
  • Lambda functions as arguments
  • Interfacing with objects having length properties
    • arguments
    • NodeList
    • Strings

Problems


  1. Return interface inconsistency
  2. No chaining
  3. Not every Object has length property
  4. No internal access to methods
  5. No conditional breaks
  6. No warranty of being untouched
  7. How to mixin with our modules
  8. Possible semantic collision
  9. Context mutation
  10. Emptiness unhandled
  11. Only mutator methods has references to values


And confusion..



Object.defineProperty(Array,"forEach",{
value:function(i,val){
    alert('hi: '+i+" : "+val)
}});
[1,2].forEach(function(val,i){
	alert('hi proto: '+i+" : "+val)
});
Array.forEach([1,2],function(val,i){
	alert('hi static: '+i+" : "+val)
});



Array generics is not consistently operating on Objects



can't call on Object..


   alert([].map.call({head:15,title:30},function(s){return s+'px'}).
join(', '));


Sometimes can, Holy Grail..



var o={foo:"foo"}
Array.push(o, 'foo');
Array.push(o, bar);
alert( o.toSource() );//prints:({foo:"foo", length:1, 1:"bar"})


Context mutations are forbidden!



var r=
[
{id:0,title:'anyamtyukja'}
].
filter(function(book){
  alert(book.id+" : "+book.title+" : "+this.author);
  return book.id==4},
{author:'petofi'});


Where has my authors disappeared?



r.forEach(function(book){
    alert(book.id+" : "+this.author);//prints 0+" : "+undefned
})


"How about emulating an Array inside an Object?"

@Angus Croll


having trouble with missing length



let's iterate through Object to mimic index



var index = 0;
for(var prop in this){
    if(!this.__lookupGetter__(prop) && 
       this.constructor!=Array){
       (function(thisIndex, thisProp){
          Object.defineProperty(obj, thisIndex, {
                get: function(){return obj[thisProp]}
                , enumerable: true
                , configurable: true
                , writeable: true
          });
       })(index, prop)
       index++;
    }
}



Update as well



Object.defineProperty(obj, 'length', {
  get: function(){
    return obj.update();
  }
  set: function(){
    return obj.update();
  }
  , configurable : false
  , enumerable   : false
  , writeable    : true
});
obj.length;



OK, Check the source dude!



Seems to work..



var myObj={jozsi:2,tamas:5};
//wrap up our object extensional expressions to a method;
extendObj_as_array(myObj);
alert('myObj is now an emulated kind of array '+myObj.length);

//adding new, uninitialized property also as array indices;
myObj.aron=0;



Oh, no...



//it is not possible to query the newly added index to myObj, 
//because index is actually uninitialized until the length is queried;
alert('newly added index is undefined: '+myObj[2]);

//length is queried, indices are being updated!
alert('indices are updated: '+myObj.length);

//Now it is possible to query the newly added index to myObj;
alert('newly added index is now defined: '+myObj[2]);

//array functionality works on objects;
alert('mapping values as pixels: '+[].map.call(myObj,function(s){return s+'px'}).join(', ')); 
//prints "2px, 5px, 0px"



Object is a pile of key-value pair,
seemingly retain the order they added



Array is just a special kind of Object..



Array methods should therefor be consistent with Object methods!



Enumerable.js



Encapsulate differences!



//argument defaults to be Object!
var enum=enumerable();
var enum=enumerable([]);
var enum=enumerable({});
var enum=enumerable(new enumerable);



let us work!




//note! vacuum.db.tables[table] is a valid JavaScript Object.
enumerable(vacuum.db.tables[table]).
sort({againstVal:true,func:function(a,b){return a.frequency<b.frequency}}).
.forEach(function(i,val){
     if(it.isTypeOf(val,[Object]).
        ANDNOT({macro:'$this.id=='+self.defaultRecord}).true())
     {
        self.record(table,val.id);
     }
     return true;
});


Features & Principles


  • Futureproof against any upcoming Object type
  • Functional break support
  • Recursion support
  • Undo-redo transactions
  • Every enumerable instance is handled as one kind
  • Zero confusion
  • Closer to functional paradigms
  • Returning interface consistency
  • Rock solid ordering management

Features based on ordering


  • Comparison between different types
  • Order based comparisons
  • fromItem/toItem support(bubbling)


Bibliograpy




Thanks for your interest!


@ZLudany

enumerable.js

By zludany

enumerable.js

Enumerable.js let us hide differences between native Objects and ES5 compatible Arrays

  • 71