Have you ever dreamed about a cross platform, consistent, copy and paste ready, JavaScript code style that gives you control on basically everything that is going on runtime?
###What Is This About Well, considering Proxy is one of those features nobody can't wait to use since ever, together with Harmony Object.observe(obj, observer), I would bet you did!
This is what this project is about, the concept there since ECMAScript 3rd Edition nobody thought/used/embraced/promoted before.
... we learned all single chars of the specs and never used them to make things right for us, right for every dev, isn't it?
- we've been asking for getters and setters without promoting a simple
obj.set(key, value)andobj.get(key)approach - we've be whining about missing private properties, being forced by someone to use
obj.hasOwnProperty()per eachfor/initeration, without even considering thathasOwnProperty()could be actually the key to understand if a property is private or public using inheritance as that wasn't me, is not my thing approach - we've been looking for notifications on what's going on, a better way to debug everything that is happening in our code ... with current status: a nightmare of stack-traces with anonymous callbacks or undefined is not defined pointless messages
- we've been hoping for some mechanism able to act like, as example,
__getand__setin php programming language - we've been hoping for something even more evil as the good old
__noSuchMethod__was - we've been writing
for/inloops in the same, repeated, boring, error prone way, we all know - we've been using previous point to retrieve also objects values
- we've never understood if
delete obj.key;returningtruemeant we actually deleted something - we've been stuck in the middle of all possible browser version to bowser version updates and quirks and I'm not talking about IE only
- we've been afraid of extending
Object.prototypebecause the language never provided non enumerable properties, without enforcing patterns similar toObject.keys()which together withforEachis the newfor/in(if hasownproperty)boring loop - ... etc ... etc ...
###Basically Our Fault The problem is simple, we never agreed on anything except for few methods everyone re-implemented in this or that native prototype and with this or that inconsistency ... well done us! We had a better solution 10 years ago but we have still the same problems today: the write once and run everywhere myth we, in first place, didn't make it possible.
###A Different Approach That Will Fail You read correctly, instead of deciding what's good and work now and what doesn't together, we all complain about this and that without getting things done and this project won't be different. Unfortunately, this happens also too often in ES mailing list and this is one of the reasons things change sometimes way too slow.
###Even Thought... I will try in any case for those brave developers that would like to contribute or improve the idea, for those developers without many external dependencies, or able to make those external dependencies work with AnotherJS as well in order to have all advantages, without compromising performances that much for real world use cases (you have to consider benefits VS raw performance).
So, here you can see how this environment in pure JS is different ... I swear, this is not a joke, you can find 100% code coverage with tests here
###AnotherJS API This is the Object.prototype in alphabetic order:
Object#contains(value:any):booleanreturnstrueonly if theobjecthas thatvaluein its own propertiesObject#del(key:string):booleanreturnstrueif theobjecthad own propertykeyand it was removed (deleteis not usable in ES3 while the operation might returntrueregardless what happened to the object status)Object#get(key:string):anyreturns the value associated toobject[key]orundefinedif noneObject#has(key:string):booleanreturnstrueifobject.hasOwnProperty(key)and key is not a reserved word (explained later on)Object#invoke(key:string[,arg0[,arg1[,argN]]]):anyreturns the equivalent ofobject[key].call(object[,arg0[,arg1[,argN]]])Object#invokeArgs(key:string[,[arg0,arg1,argN]]):anyreturns the equivalent ofobject[key].apply(object[,[arg0,arg1,argN]])Object#invokeBound(key:string)returns the equivalent ofobject[key].bind(object)except this is created only once perkeyname rather than N times. This makes common usage of bound methods memory and CPU safer.Object#keys():Arrayreturns an array of object own enumerable keysObject#set(key:string, value:any)returnsvalueafter setting thekeyasobject[key] = valueObject#values():Arrayreturns an array of object own enumerable values
And this is the Object static API in alphabetic order:
Object.intercept(o:Object, f:Function):oregisters the function as interceptor and returns the original, first argument, object.Object.observe(o:Object, f:Function):oregisters the function as observer and returns the original, first argument, object. Works like native proposal available in Chrome CanaryObject.unintercept(o:Object, f:Function):oremoves the function from notifications and returns the original, first argument, object.Object.unobserve(o:Object, f:Function)removes the function from notifications and returns the original, first argument, object.
###Don't Be Afraid The fact I'm extending Object.prototype in 2012 does not mean I am mental or noob ... I am coding JS since IE4 and I've seen every bloody piece of code interacting over for/in loops through the obj.hasOwnProperty(key) pattern so ... really, don't be worried about this. Said that, the aim of this project is actually to promote a different paradigm such:
function doSomething(key) { var value = this.get(key); if (value.needsUpdates) { this.set(key, update(value)) } } obj.keys().forEach(doSomething, obj); So once again, if you use this project for what it provides, you know your own objects and your own way to interact with them in an optimal way. Libraries unaware of this library, will still be safe using the boring for/in loop all over the place, without using ES5 non enumerable possibility, etc etc ...
###Reserved Words These are the only "problematic" keys an object could have able to potentially cause problems to external libraries and only if Object.observe() or Object.intercept() have been used with the specific object, otherwise there's nothing to worry about. Since libraries not aware of AnotherJS will never use those Object methods, again nothing to really worry about but you are surely welcome to update those libraries and promote AnotherJS version in your own repository, these will be linked here too!
###On Object.intercept(o,f) Any time we o.get(key), o.set(key, value), or o.invoke(key, arg0, arg1), together with invokeArgs(key, [arg0,arg1]) and (invokeBound(key))(arg0, arg1) each function registered with Object.intercept(o,f) will be called synchronously. First come, first serve is also the pattern used to overwrite the result of the operation since of course, the first one that can observe or intercept an object, is usually considered the owner of the object.
var o = {hello: function (name) { alert( "Hi " + name + ", my name is " + this.get("name") ); }}; Object.intercept(o, function (record) { record.object === o; record.type; // "get", "set" or "invoke" record.name; // "name" or "hello" record.value;// "Andrea" or arguments }); o.set("name", "Andrea"); o.invoke("hello", "everybody"); // or ... o.hello("everybody"); // Hi everybody, my name is Andrea ###Performance If you are concerned about performances I understand. Interacting with all objects like this might not look like the best thing ever to do but here the deal: you don't have to interact with all objects like that. That's correct, when raw performances are essential and objects don't need to be observable or interceptable, the simple obj.prop, obj.prop = value will still work as expected. You might find handy at that point the fact other methods such has(key) or contains(value) still works as expected, as well as keys() and values() could be still used without any sort of problem. Last, but not least, you can have an idea of number of operations per second you can have with or without AnotherJS get and realize in some browser it is faster than native ES5 getter.
###More Documentation Coming Soon It's not easy at all to write all examples and explain everything here so more is coming but you can already try in console the whole API with any browser you want. Right now we are talking about Object only but others native constructor are coming into AnotherJS pretty soon.
###Tests For the web, open test.html and you are ready to go. Use polpetta if your browser does not load file protocol. For node.js, simply node test/Object.js from this folder.