Wednesday, December 14, 2005

Safari and the String.replace() method

JavaScript strings have a cool method called replace() which allows you to supply a regular expression and replace the matched bits of the string with another string.

var str = "my dog has fleas";
str = str.replace(/dog/, "cat");

Output:

my cat has fleas

One of the cooler things about this is you can provide an expression as the second argument. This can be a variable:

var str = "my dog has fleas";
var str2 = "cat"
str = str.replace(/dog/, str2);

...or even a function:

function Cat() {
  return "cat";
}
str = str.replace(/dog/, Cat);

This works great in IE, and Firefox on both Windows and OS X.

But Safari? Not so much. Here's the output of that last example in Safari:

my function Cat() {return "cat";} has fleas

Ugh, what happened? It appears that when given a function in this context, Safari does not evaluate it as an expression, but instead calls the toString() method of the function, casting it into a string.

I haven't found a workaround. Have you?

12 Comments:

At 8:45 AM, Blogger scottandrew said...

Artem: yes, that was one of the things I tried, but it didn't work. Apparently the second argument needs to be invoked by replace() when a match is found, so that match variables like $0, $1, etc. can be passed to it.

 
At 11:12 AM, Blogger Brent Ashley said...

Hi Scott;

Does this work?

str.replace(/dog/,Cat() + "");

or possibly

str.replace(/dog/,(Cat() + ""));

Perhaps it will commute the dynamic function call to a fixed string at runtime.

 
At 11:31 AM, Blogger David said...

There's no nice way to do this in Safari (nor in IE5.5). Once you put () after the function name it gets called which is no good since you want to be able to handle $1, $2, etc.

Does "cry myself to sleep at night" count as a solution?

 
At 2:34 PM, Blogger scottandrew said...

Brent: I tried that, but it only caused both FF and IE to invoke toString(), behaving the same as Safari :)

 
At 4:28 PM, Blogger Brent Ashley said...

Would brackets around the function call get its value before toString-ing it?

str.replace(/dog/,(Cat()) + "");

Perhaps I need me a mac emulator so I don't introduce such latency into this comment-driven debug loop. Reminds me of debugging in the late 70's where you'd submit your card stack on Monday, get an error back on Tuesday, change the one card and resubmit, only to get another error on Wednesday.

I guess I'm dating myself...

 
At 4:58 PM, Blogger Geoffrey Garen said...

Would you mind providing a sample html file that demonstrates this bug? I tried to reproduce it using the instructions above but couldn't. You can see the test case I used at http://bugzilla.opendarwin.org/show_bug.cgi?id=6128.

Thanks.

 
At 11:11 AM, Blogger scottandrew said...

Geoffrey: are you using Safari nightly builds? I just found out that the issue is fixed in the CVS tree but not in any public-released version of Safari.

 
At 5:53 PM, Blogger Unknown said...

you could try

var myobj = new Object();
myobj.toString = function(){
//the code I want to run
}

str = str.replace(/dog/, myobj );

Hopefully the 'toString' function will be called each time. Haven't tried it, but it may work

 
At 2:48 PM, Blogger Jinghao said...

Is it really that big of a deal? How much market share does Safari occupy anyway?

 
At 4:31 PM, Anonymous Anonymous said...

Brent: I tried that, but it only caused both FF and IE to invoke toString(), behaving the same as Safari :)
Buy paxil without prescription
risperdal generic buy
Buy geriforte
Buy geriforte no prescription pharmacy
Buy topamax no prescription
buy Arimidex
Amoxil Online
buy ambien online no prescription

 
At 1:01 PM, Anonymous Anonymous said...

Men's Health and Women's Health, Anti-Diabetic and Anti Allergic, General Health and Sleeping Aid. All Drugs at

We have multiple sites that are mirrored with each other and the products are advertised in either EURO, or YEN, or USD or GBP. This gives the customer the flexibility to choose their preferred currency that they would like to be charged in.

Mentat from Canada
Arimidex from Canada

Buy ambien no prescription
Buy Avandia no prescription

 
At 5:00 PM, Anonymous Anonymous said...

Excellent article and commentary! Online Penny Slots and Online Penny Slots Machines

 

Post a Comment

<< Home