My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Thursday, August 16, 2012

JavaScript recent Bits and Bobs

Quick post about few things landed, or not yet, in JavaScript world.

preciseTime()

In this era loads of +new Date, JSC offers since quite a while a handy global function called preciseTime().
Since this function offers more accuracy than milliseconds, and I am talking about microseconds, which is 1/1000 of a millisecond, it's the best option we have to measure benchmarks or be sure that some time elapsed between two statements in a synchronous code flow.

You might don't know that a loop between new Date and another new Date could produce completely unexpected results such a negative integer which is kinda unexpected since zero is the best case we would consider.

This behavior is behind ticks and clocks, more or less same reason setTimeout or setInterval have never been accurate in therms of delay.

preciseTime, this is the obvious name of my latest git repository, could be shimmed or polyfilled quite easily via a node module I can't npm install for some reason, or through java.lang.System.nanoTime for Rhino.

enjoy!

Object.getPropertyNames()

In MDN Proxy Fundamental Traps chapter there are two functions I was kinda waiting for, and one of these is Object.getPropertyNames().

As you might know, Object.keys(object) returns an array of enumerable object properties.
A similar behavior could be obtained via this shim:

// warning: this is not fully ES5 standard
"keys" in Object || !function(hasOwnProperty){
Object.keys = function keys(object) {
var keys = [], key;
for (key in object)
// not considering IE < 9 quirks
hasOwnProperty.call(object, key) && keys.push(key);
;
return keys;
};
}({}.hasOwnProperty);


On the other hand, Object.getOwnPropertyNames returns an Array of all properties defined in the object, even those not enumerable or as getters/setters, but without considering inherited properties.
For all ES3 browsers is basically the same of above Object.keys() shim since it's not possible to define not enumerable properties in a meaningful way.
To be really honest, probably all IE < 9 browsers should use the check over isPropertyEnumerable() check via Object.keys, and leave the provided shim as it is since actually, those not enumerable properties are those that this function could return in a meaningful way, and talking about shims ... never mind ...

In ES5 world there's no other way to retrieve all properties names defined in an object so this methods is pure awesomeness!

Right ... What About Object.getPropertyNames()

What is not possible right now, and in a world where inheritance is all over the place as JS world is, is the ability to retrieve not only own properties, but inherited properties too.
In a duck typed system we need to know all characteristics of an object to be sure "it's a duck". Right now there's no standard way to obtain all properties an object could use, and this is where Object.getPropertyNames() becomes handy: you receive all inherited properties of an object too, together, of course, with own properties.
In my shim, this is obtained through the __proto__ de facto standard property.


At this point we can recognize a duck properly, the only method eventually missing is the one able to give us a list of not enumerable properties per each object ... but with these tools, we can create one, if truly necessary.

Object.getPropertyDescriptor()

Oh well, this is about another annoying thing ... the fact we know that obj instanceof Class but we have to be upside-down to know if a property, defined as default in the Class.prototype has been redefined or it's simply that bloody default.
This is about this method, shimmed in the previous gist as well, and able to retrieve the descriptor of a property that might, or might not, be inherited. How cool is that?

The only thing I am not sure about, is if the method should consider up to prototype === null, including Object.prototype or not ... right now is not, since I believe nobody would ever check for hasownProperty descriptor, as example, with a generic object.

global methods, classes, and shit

This is more a hint, whenever you are curious about what's exposed through your global object, you can simply perform this check, and inside an about:blank page:

console.log(
Object.getOwnPropertyNames(this).sort().join("\n")
);

Where if you want alphabetic order, you might consider this elaborated version if previous one did not work as expected.
Run it once in your browser, environment, console:

!function(global){
function alphabetically(a, b){
var
alen = a.length,
blen = b.length,
len = Math.min(alen, blen),
i = 0,
ac, bc, c
;
while (i < len) {
ac = a.charCodeAt(i);
bc = b.charCodeAt(i);
c = ac - bc;
if (c) return c;
++i;
}
return alen - blen;
}
var getOwnPropertyNames = Object.getOwnPropertyNames;
if (!getOwnPropertyNames) {
getOwnPropertyNames = function getOwnPropertyNames(object) {
var hasOwnProperty = {}.hasOwnproperty, keys = [], key;
for (key in object)
hasOwnProperty.call(object, key) && keys.push(key)
;
return keys;
};
}
function getAllKeys(object, ordered) {
var keys = getOwnPropertyNames(object);
ordered && keys.sort(alphabetically);
return keys;
}
console.log(getAllKeys(global,1).join("\n"));
}(this);

8 comments:

John-David said...

Your `Object.keys` implementation doesn't follow spec. It should throw a TypeError when passed a non-Object type. See http://es5.github.com/#x15.2.3.14. I don't see much use of shimming `Object.keys` when other ES5 methods are required and the `keys` shim isn't spec compliant or covering common iteration issues. Instead why not make a private utility function and use that or native `Object.keys` if it exists.

John-David said...

Instead of using a compare function with `Array#sort` why not just use `sort` without a compare function? I compared results of things like `["zz", "AA", "ZZ", "aa", "01"]` with and without your compare function and they both returned the same order of `["01", "AA", "ZZ", "aa", "zz"]`.

Andrea Giammarchi said...

I was testing with real global data and could not remember why I had to use that function to grant same results cross platform ...

Andrea Giammarchi said...

Object.keys was an example, lo-dash orunderscore are surely better utilities than that 1 minute shim ;-)

Andrea Giammarchi said...

actually just sort() looks fine ... oh well, I have too many nighties installed :D

kentaromiura said...

About preciseTime, I think it would be good if I took my old http://iejst.codeplex.com/ project and reflect that api name, so you could cross test on IE too :P

but would anyone use it if I update it?

Andrea Giammarchi said...

here the answer ... about using that ... why are you interested in older IE tests ... you already know these performs crap :D

kentaromiura said...

Why you ask?
1) Because I can
2) Because I have already done it :P
3) Because if performance are crap that not means you shouldn't look for it, sometimes if it performs poor in IE is a "smell" that something is wrong with you code, and you know, some people are still forced to use IE nowadays, so I though it would be useful to give these poor guys a way to profile their code.

Anyway I don't mind, I though it would be good to support ie6+, but seems like you're not interested, I mean, I can understand this, I'm not interested in ie<8 anymore.

Oh, totally unrelated but probably it would be a good idea to support msNow, oNow and mozNow too, if ever they will implement it, you will already work.