Forum Home
Press F1
 
Thread ID: 75184 2006-12-19 08:31:00 Javascript Guru Needed Erayd (23) Press F1
Post ID Timestamp Content User
507983 2006-12-19 11:57:00 You can't assign to "this". Javascript variables are references, not values. You could do something like this in C++, but it simply doesn't make sense in Javascript. It also violates good design principles.

The solution to this is to return an array containing the components. This is more general, does not alter the object itself in any way and can be used more flexibly. You might also like to consider not altering the String prototype. Just because you can do it doesn't make it a good idea - this is how you create horrible naming conflicts that are very difficult to diagnose and debug. Try this:

splitStringAtIndex = function(string, index) {
var a = string.substr(0, index);
var b = string.substr(index);
return([a,b]);
};

... somewhere else ...
components = splitStringAtIndex(string, 5);
string = components[0];
suffix = components[1];

EDIT: I just looked at your signature again and you obviously know PHP. I believe PHP variables represent a value, so I see where the confusion came from. You may like to read up on this - most scripting languages use reference variables.
TGoddard (7263)
507984 2006-12-19 12:30:00 Thanks for that TGoddard - I didn't know that about Javascript variables, and it certainly explains why I was having problems. Unfortunately though, the whole reason I was trying to define a prototype method was because I wanted to avoid the array stuff - in an ideal world, I want to be able to do something like while(s = someString.shift(5)) {doSomething();}, with String::shift automatically updating the variable. In effect, it would be using someString as a FIFO buffer (not quite but you get the idea). I could define shift() externally, but then it gets messy - I was hoping to define a method that could be used across all instances of String.

The goal is to write a Javascript parser to unserialize a PHP serialized multidimensional array, as this would keep a lot of the flexibility of using XML, but without the overhead of the XML parsers - resulting in less server & client load, and a whole lot less DOM access / XML code.
Erayd (23)
507985 2006-12-19 13:14:00 A good way to handle something like this is to make all of the iteration and indexing logic internal and simply tell it what to do with each bit:

String.prototype.forEachFragment = function(fragmentLength, action) {
string = this;
while (string.length > 0) {
components = splitStringAtIndex(string, fragmentLength - 1);
action(components[0]);
string = components[1];
}
}

...

sequence = "ATCCGATAGCATAGCCGT"
aa = new Array();
sequence.forEachFragment(3, function(fragment) {aa.push(getNucleotide(fragment))}); // Does this work? I'm not sure how function scope works in Javascript.

By the way, as it turns out your original sample is actually overriding an existing function called "split". If a library you were using depended on it then you would have serious problems. It is always best to use very specific names if you have to add your own functions to an existing namespace/object.
TGoddard (7263)
507986 2006-12-19 19:18:00 By the way, as it turns out your original sample is actually overriding an existing function called "split". If a library you were using depended on it then you would have serious problems. It is always best to use very specific names if you have to add your own functions to an existing namespace/object.Yikes! Why does it do that - my method is called shift, and I was under the impression that in order to override the 'split' method, mine would also need to be named 'split'. I did take a look at the existing String methods to avoid conflicts, but obviously this wasn't enough.

The above way of doing things looks promising, but still isn't much good to me unless I can pass the string as a pointer rather than as a normal variable - where the problem comes in is needing the original string to be modified in addition to returning a value. A function like that took a string pointer as an argument would fit this, or a prototype function on String, provided that I can get some kind of writable handle. I can't just modify the original string inline with the rest of the code though - this operation needs to be performed many, many times, in a lot of different places and doing it with several (of the same) code lines every time would result in serious bulk.
Erayd (23)
507987 2006-12-19 22:17:00 Negative. There's tons of help here

Sorry
gum digger (6100)
507988 2006-12-19 23:19:00 SorryShhh. No need to be sorry. Besides, you might invoke the wrath of Metla at us for being wimpy daffodil kissing babies. ;) Greg (193)
507989 2006-12-20 06:52:00 Yikes! Why does it do that - my method is called shift, and I was under the impression that in order to override the 'split' method, mine would also need to be named 'split'. I did take a look at the existing String methods to avoid conflicts, but obviously this wasn't enough.

My apologies, I thought your method was named "split" and didn't re-read it. This doesn't cause a problem immediately, but what would happen if another library or tool also tried to create a "shift" method? It is a good idea to try to pick names which are more likely to be unique.


The above way of doing things looks promising, but still isn't much good to me unless I can pass the string as a pointer rather than as a normal variable - where the problem comes in is needing the original string to be modified in addition to returning a value. A function like that took a string pointer as an argument would fit this, or a prototype function on String, provided that I can get some kind of writable handle. I can't just modify the original string inline with the rest of the code though - this operation needs to be performed many, many times, in a lot of different places and doing it with several (of the same) code lines every time would result in serious bulk.

Javascript strings appear to be immutable, just like Java ones. This means that you cannot change them after creation. You cannot modify an existing string, only create new strings from it. Javascript doesn't have pointers - all variables are references. When you pass a parameter no copying of objects takes place. When no references to an object exist any more, it will be garbage collected.

What exactly are you trying to do here? Perhaps with some context it might be easier to work out a way of performing the task in a clean way.
TGoddard (7263)
507990 2006-12-20 12:18:00 ...but what would happen if another library or tool also tried to create a "shift" method?This will never happen here - ChatF1 is entirely my own creation, and written in a text editor - it uses no exteral libraries or tools. I also don't plan to use anything external, as it was partly a project that I could use to learn AJAX techniques. I also enjoy reinventing the wheel; I find it's a good way to learn new things. However you do raise a good point, and it's certainly something for me to bear in mind for other projects.


What exactly are you trying to do here? Perhaps with some context it might be easier to work out a way of performing the task in a clean way.What I am trying to do is write a parser for PHP serialized arrays that will take a string, and generate a multidimensional Javascript array from it. This saves the overhead of using XML parsers, but keeps all the things I was using XML for in the frst place. In order to get the data from the string, I need to read it in sections n characters long. The first thing I looked for was a shift method like Array has, but found there wasn't one. As it's a method I would use a lot elsewhere too, I decided to write it, as parsing strings of various types is something that the ChatF1 software needs to do a lot of, and at the moment the technique it uses is quite inefficient in terms of code bulk, and has a limited flexibility.


Javascript strings appear to be immutable, just like Java ones. This means that you cannot change them after creation. You cannot modify an existing string, only create new strings from it.If this is the case, is there some way to cause the original reference to point to something else(a new String containing the new value), and simply allow the old String to die?
Erayd (23)
507991 2006-12-22 11:59:00 ^ bump Erayd (23)
507992 2006-12-22 23:53:00 Don't reinvent this particular wheel! It has already been solved a thousand times. Since you control both the server and the client (and security is not too mch of a concern) you can simply generate JSON on the server (using one of the many PHP JSON libraries) and eval it in the browser to get your array back out.

Why are you trying to split at a particular index here? The code for this is simple:



String.prototype.multiSplit = function(delimiters) {
delimiters = delimiters.slice();
var delimiter = delimiters.shift();
var output = this.split(delimiter);
if (delimiters.length > 0) {
for (var i = 0; i < output.length; ++i) {
output[i] = output[i].multiSplit(delimiters);
}
}
return output;
}


var myString = "This is one array;This is another"
myString.multiSplit([";", " "])

produces [["This","is","one","array"],["This","is","another"]]

This takes an array of delimiters and splits it into a multidimensional array. Notice that this method does not alter the original objects in any way as there is no good reason for it to do so.

When writing code you should try to be aware of which methods only access information from an object and which alter it ("mutators"). Mutators should be as simple as possible, it should be clear what they do and you should never use a mutator when you don't need to. By minimising side effects you make your code much more flexible and easier to debug.

About the naming thing - this is a valid point. Since this is a browser application, however, you must always assume that custom Javascript libraries may be loaded. Some vendors extend their implementation beyond the standard. It is easy enough to use a more descriptive name and will make your code more reliable.
TGoddard (7263)
1 2 3