Page 1 of 2 Javascript, being an interpreted language, can modify its own code as it runs. Self-modifying code can be dangerous but you should know about it and how it works. If you would like to experiment, read on.
Now available as a book from your local Amazon.
JavaScript Jems: The Amazing Parts
JavaScript Jems - Functional And Not Quite Functional
Original drafts of chapters.
Contents
- JavaScript Patterns
Why JavaScript is a Jem
- Objects with Values in JavaScript*
- Private Functions In JavaScript
- Chaining - Fluent Interfaces In JavaScript*
- Active Logic, Truthy and Falsey*
- The Confusing Comma In JavaScript*
- Self Modifying Code*
- Lambda expressions
- Meta Programming Using Proxy
- Master JavaScript Regular Expressions
- The Function Approach To Programming
<ASIN:1871962579>
<ASIN:1871962560>
<ASIN:1871962501>
<ASIN:1871962528>
When programming was a young subject and vacuum tubes ruled the earth, a very powerful but very scary technique was invented – self-modifying code.
The whole beauty of the stored program computer design was that the data and program were treated in the same way. A program plus the data it needed to work with were loaded into memory and the program simply accessed and modified the data as required.
This idea was so new and powerful that programmers often didn’t really distinguish between the program and the data and allowed one part of the program to modify another part of the program.
Self-modifying code can effectively re-write itself as it runs and as such you can guess that it’s powerful but you should also be able to see that it creates a nightmare for debugging and generally understanding what is going on.
After all, if code is self modifying, there is no simple static piece of text that can be read through to check it makes sense. You have to read the code and keep updating what the program is as it modifies itself.
As a result self-modifying code not only fell out of favour, it was actively demonised as something that only really evil programming languages would allow you to do. So if you think that self-modifying code has just been invented and is something connected with the new wave of dynamic languages think again – it’s old but still relatively untamed.
After all of this you might be surprised to learn that JavaScript allows self-modifying code. Indeed most interpreted or dynamic languages do. The point being that self modification isn’t always bad – you just need to work hard to keep it under control and that means keep it simple.
Dynamic functions - function to string
The reason why JavaScript supports runtime modifiable code is that the program itself is just data stored in a variable. Consider the way you can define a function:
function myfunc1(){alert("MyFunc 1");
which is almost exactly equivalent to:
myFunc1=function(){alert("My Func 1")};
The second form looks like a variable assignment and indeed it is. If you don’t believe me try:
alert(myFunc1);
and you will see the text of the function just as if it was a string.
However MyFunc1 isn’t actually a string – it’s a Function object. What is going on here is that the Function object's toString method is being called and this returns a string representation of the function:
alert(myFunc1.toString());
Although this isn’t guaranteed, it works in all the major browsers.
There is also a rather more non-standard method called toSource which works in Firefox but not in most other browsers. Also notice that you can’t see the source code for internally defined functions only user defined functions.
You can take a function and convert it into a string using:
myString=myFunc1.toString(); alert(myString);
or you can use the String object’s constructor and an implied call to the toString method:
myString=new String(myFunc1);
Of course now that you have the function represented as a string you can edit it in any way that you like.
For example, you can change the “1” into a “2” using:
myString=myString.replace("1","2"); alert(myString);
This changes what is stored in the string into:
function(){alert("My Func 2")};
Notice that this is a string and there is no way you can directly execute this new function, i.e.
myString();
doesn’t do anything.
How to make a string back into a function is our next challenge.
The round trip - string to function
The real question is how to get the string back into a function and there are a number of ways of doing this.
The most direct is to use the Function object’s constructor. If you write:
myFunc=new Function(“arg1”,“arg2”…“statements”);
the new function will be created with the specified arguments and statements.
Notice that the number of arguments can't be variable as the last string passed to the constructor is taken to be the body of the new function.
To use this with our string we simply have to strip off the “function()” part of the string. Unfortunately some browsers place a space between “function” and “()” and some don’t.
You can probably improve on this simple minded implementation of the constructor:
myFunc2=new Function(myString. replace("function()","") .replace("function ()","")); myFunc2();
The easy way out is to simply attempt to replace function followed by no space or followed by one space. In the real world you would use a regular expression and spend much more time getting it right.
Notice that there are no parameters used in this function and writing a routine to convert any function in the form of a string into a real function using the Function object constructor is slightly more difficult as it involves a lot of string manipulation to get things in the correct form.
Fortunately there is an easier method based on using eval.
|