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/in
iteration, 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,
__get
and__set
in php programming language - we've been hoping for something even more evil as the good old
__noSuchMethod__
was - we've been writing
for/in
loops 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;
returningtrue
meant 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.prototype
because the language never provided non enumerable properties, without enforcing patterns similar toObject.keys()
which together withforEach
is 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):boolean
returnstrue
only if theobject
has thatvalue
in its own propertiesObject#del(key:string):boolean
returnstrue
if theobject
had own propertykey
and it was removed (delete
is not usable in ES3 while the operation might returntrue
regardless what happened to the object status)Object#get(key:string):any
returns the value associated toobject[key]
orundefined
if noneObject#has(key:string):boolean
returnstrue
ifobject.hasOwnProperty(key)
and key is not a reserved word (explained later on)Object#invoke(key:string[,arg0[,arg1[,argN]]]):any
returns the equivalent ofobject[key].call(object[,arg0[,arg1[,argN]]])
Object#invokeArgs(key:string[,[arg0,arg1,argN]]):any
returns 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 perkey
name rather than N times. This makes common usage of bound methods memory and CPU safer.Object#keys():Array
returns an array of object own enumerable keysObject#set(key:string, value:any)
returnsvalue
after setting thekey
asobject[key] = value
Object#values():Array
returns an array of object own enumerable values
And this is the Object
static API in alphabetic order:
Object.intercept(o:Object, f:Function):o
registers the function as interceptor and returns the original, first argument, object.Object.observe(o:Object, f:Function):o
registers the function as observer and returns the original, first argument, object. Works like native proposal available in Chrome CanaryObject.unintercept(o:Object, f:Function):o
removes 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.