Thursday, October 22, 2009

JavaScript For In Madness

Have you never instinctively written a for in loop like the next one, instantly correcting it since you need a variable to perform it?

for(var k in {oops:null}){
// cool, got "k" here ...
// now how do I get
// the bloody "oops" value?
}

This quick post talks about above nonsense case providing a solution I will explain only if anybody will be interested about it, since (I am quite lazy and tired right now and ...) I think I've been able to solve the trick using almost every JavaScript bad practice :D

Runtime Assigned For In Loop



(function(self, Function){
// Another (C) WebReflection Silly Idea
"use strict"; // Mit Style Weirdness
var $o;
self.o = function o($){
if(!$)
self.o = $o;
else {
$o = self.o;
self.o = Function(
"$", "return function o(" +
new Array(($.length || 0) + 1).join(",k").slice(1) +
"){return $(arguments[0])}"
)(o);
for(var k in $)
self.o[k] = $[k]
;
};
return $;
};
})(this, Function);


WTF Is That

Above agglomerate of dynamic assignments/compositions let us perform a forIn without creating (virtually speaking) a variable. How?

for(var k in o({a:"b", c:"d"})){
alert([k, o[k]]);
};

In few words we don't need to define the "o" object in any place. The trick works as expected with blocked properties, as length is for a function, name, and whatever else was assigned to the object and even nested

for(var k in o({
length:123,
name:"test"
})){

alert([k, o[k]]);

// nested for in ...
for(var k in o({a:"b"}))
alert([k, o[k]])
;

o(); // back in town parent object

alert(o.name); // test
};

Isn't it cool? Even with Arrays!

for(var k in o([1, 2, 3])){
alert([k, o[k]]);
// 0,1
// 1,2
// 2,3
};

The good part is that break will work as expected and the changed object is quite static since it is a function, looped over original object properties.

Why This Abomination

Well, let's say with let and var we can do what we want in a generic for loop but we are kinda stuck with a single variable with a "for in" one.
What would be truly nice in my opinion is the possibility to implement this kind of syntax:

for(var o = {a:"b"}, k; k in o){
// common loop with o and o[k]
};

Something similar to PHP world where we have:

foreach(array('a'=>'b') as $key => $value){
// do stuff and forget about the config variable
}

I am pretty much sure JavaScript will never implement above syntax but hey, that's why I have created a monster I'll probably never use in my programming life :P

The main trick about supported length property is described in this post.

No comments:

Post a Comment