This project will include automatically a lot of standard JS 1.5 methods or functions, and Array.map is one of those.
While I'm testing some proto performances, I've thought about a really simple way to switch from an array or from a node list (getElementsByTagName) with a simple, fast and single line of function.
// old example version
// function _A(a){return [].map.call(a,function(a){return a})};
// new version, Daniel suggest, faster and doesn't require any prototype !
function _A(a){return [].slice.call(a)};
and that's all, do You like it ?
As first point, You need FireFox 1 or greater (or Mozilla if You prefere) or this short piece of code:
if(!Array.prototype.map) Array.prototype.map = function(callback){
for(var i = 0, j = this.length, result = new Array(j), self = arguments[1], u; i < j; i++) {
if(this[i] !== u)
result[i] = callback.call(self, this[i], i, this);
};
return result;
};
Then You have "everything You need" to get quickly every iterable element.
These are just two examples
function sort(){
return _A(arguments).sort().join("<br />");
};
document.writeln(sort("Luke", "Jabba", "Fenner"));
document.writeln(sort("c", "a", "b"));
var firstScript = _A(document.getElementsByTagName("script")).shift();
alert(firstScript);
var allUnorderedList = _A(document.getElementsByTagName("ul"));
alert(_A(null).constructor === Array); // true ;-)
These nice trick should be used with forEach method too.
Stop for and while loops, each them !
function changeLinks(onclick){
[].forEach.apply(document.getElementsByTagName("a"),
function(link){
link.onclick = onclick;
});
};
changeLinks(function(){
window.open(this.href, "");
return false;
});
... and sure, You need forEach prototype too ...
I suppose every other JS 1.5 Array method should be cool enought to work with DOM nodes too ... do You agree ?
Are thinking about performances ? Well guys, quite the same of generic loops, even faster (works in core) with every FireFox !!!
You can use slice to create arrays. I think 'Array.prototype.slice.call(a)' works for node lists on Firefox and Opera 9, but not Safari (I can't remember if it works on Internet Explorer). So I would sniff the browser and the version and only use it when 100% sure that it is supported.
ReplyDeletesure Daniel, You can use every type of array prototype and slice should be even better (suported on IE4 too)
ReplyDeletefunction _A(a){return [].slice.call(a)};
why not ... it's cool but with map, forEach or filter You should use directly a callback to parse every object inside each arguments (and with map prototype You'll be shure browser will support them witho nodeLists too ;-))
However, how many libraries use this "tips" ? ... look inside prototype code, for example, You'll see a for loop while $A function should be:
function $A(i){return i&&i.toArray?i.toArray():[].slice.call(i)};
Do You agree ? :-)
Well ... seems that IE doesn't accept this trick with document nodes ... strange, uh ?
ReplyDelete