JavaScript summed up #7: Dynamic code
JavaScript can be a very dynamic language. To prove this, today we’ll discuss two techniques: dynamic code generation in general and “branching” (a special form).
Dynamic method generation
JavaScript allows you to add, change, or remove functions dynamically at runtime. Since functions are just objects in JavaScript (see my previous post on functions), you could just add a new one like this:
var someVariable = "Dynamic";
this["my"+ someVariable +"Function"] = function(){
// your code
}
As soon as these lines get executed, you have a function called “myDynamicFunction” at hand.
A little more complex (and more useful) example comes from John Resig: he shows a way to create “getter” and “setter” methods for the properties of an object. In this example, a “User” object, that expects an object with some properties upon initialization. For these properties, we then generate setters and getters:
function User(properties ) {
self = this;
// iterate through the properties of the object
for ( var property in properties ) {
(function(property){
// create a new getter for the property
self["get_" + property] = function() {
return properties[property];
};
// create a new setter for the property
self["set_" + property] = function(val) {
properties[property] = val;
return self;
};
})(property);
}
}
EDIT: thanks to “tester’s” comment with a correction of the above code!
Branching
Branching can be used to override an existing function with an optimized version on first run. A good example scenario is writing cross-browser code.
Imagine you have to write a function that does one thing when run in one browser, and totally different things in another one.
function xyz(){
if ( a == b ){
// do one thing
}else{
// do another thing
}
}
You would have the (in this example case admittedly small…) performance hit of at least running the condition code to distinguish between the two browsers. If the condition is quite expensive to run, or if the code will be run very very often (so that even a minimal performance improvement is desired), branching comes in handy.
Instead of checking the condition each time, it is only checked one on the first call of the function. Then, the function is rewritten – without the condition:
function xyz(){
if ( a == b ){
// override the function with the code for case A!
xyz = function() { ...code for this case... };
}else{
// override the function with the code for case B!
xyz = function() { ...code for that case... };
}
}
From the second time on, when xyz is called, there is no condition – just plain optimized code. Of course, this means that the condition should not change during runtime; it should be always the same, because it won’t get checked a second time.





3 comments
I love this JavaScript series. Keep ‘em coming!
In the getter and setter example is it really necessary to alias ‘this’ with ’self’ ?
Also, is it really necessary to use an anonymous function to create a private scope within the for loop ? It seems to work fine without both…
Hi Zorg, a reader (”tester”) pointed me to the fact: without the private scope, the example wasn’t really doing what we wanted it to do. Try it for yourself (with and without) – use whichever works out fine for you.
Leave a Comment