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?

23 Comments:

At 3:48 AM, Blogger Artem Khodush said...

I don't have safari to try it,
but the first thing that comes
to mind is to add () after the
function name, explicitly marking
it as a function call:

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

 
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:00 PM, Blogger Justin Halsall said...

Why look for workarounds when you can get it fixed:
http://webkit.opendarwin.org/quality/reporting.html
(the bugreport for the safari team)

 
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 3:05 PM, Blogger Rob said...

Uh, maybe I'm missing the boat here and I'm no whiz at Javascript, but can't you just put the result of the function call in a var and put the var in the call to String.replace()? Something like this:

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

 
At 9:07 AM, Blogger Simon said...

I found this fix today while researching this problem.

 
At 11:09 AM, Blogger David Conrad said...

I am seriously freaked out by the people suggesting something like cat() or cat() + "" or (cat()) + "" to fix this.

Why would you want to pass a function to replace rather than a string in the first place? It could only be because you want the replacement to be dynamic, possibly based on the match context or on the number of times the callback was called (perhaps you want to replace each match with successive values from a list).

In that case, the function has to be called after the match, and called once for every match. You can't call the function once and pass in its value. That would totally defeat the purpose.

Or are people actually not clear that cat passes a reference to the function, while cat() calls the function and returns a value?

 
At 5:53 PM, Blogger bert 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 10:30 AM, Blogger Administrator said...

http://best-casino-online.t35.com Best Online Casino

 
At 5:21 AM, Blogger daniele_dll said...

from andr3a

http://www.devpro.it/javascript_id_124.html

and the test page (demo link):
http://www.3site.it/CAXXATE/replace.html


It should work from IE4 to IE7, FireFox 1, 1.5, Opera 7, 8, 9, KDE 3.5 and maybe < 3.5 and Safari, 2 and maybe 1 too.

All version will parse strings as FireFox, test page should be the same on both left and right side.

Is it right ?

 
At 4:05 AM, Blogger ciscoblog said...

There is a resounding desire for meaningfull freeroll tournaments in which William Hill Online Casino > players at all levels have the opportunity to compete in tournament play when the prize money is huge... but the buyin is somewhat prohibitive for most

 
At 7:36 PM, Blogger free bet said...

There is a resounding desire for meaningfull freeroll tournaments in which Online Casino players at all levels have the opportunity to compete in tournament play when the prize money is huge... but the buyin is somewhat prohibitive for most

 
At 4:31 PM, Blogger TheCanadianMeds 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, Blogger TheCanadianMeds 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 4:12 PM, Blogger docsharp01 said...

One of the LARGEST online slots casino that accepts players from the USA is Online Slots Casinos which has 98% payouts and bonuses!

 
At 5:00 PM, Blogger docsharp01 said...

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

 
At 1:54 PM, Blogger milf said...

black mold exposureblack mold symptoms of exposurewrought iron garden gatesiron garden gates find them herefine thin hair hairstylessearch hair styles for fine thin hairnight vision binocularsbuy night vision binocularslipitor reactionslipitor allergic reactionsluxury beach resort in the philippines

afordable beach resorts in the philippineshomeopathy for eczema.baby eczema.save big with great mineral makeup bargainsmineral makeup wholesalersprodam iphone Apple prodam iphone prahacect iphone manualmanual for P 168 iphonefero 52 binocularsnight vision Fero 52 binocularsThe best night vision binoculars here

night vision binoculars bargainsfree photo albums computer programsfree software to make photo albumsfree tax formsprintable tax forms for free craftmatic air bedcraftmatic air bed adjustable info hereboyd air bedboyd night air bed lowest pricefind air beds in wisconsinbest air beds in wisconsincloud air beds

best cloud inflatable air bedssealy air beds portableportables air bedsrv luggage racksaluminum made rv luggage racksair bed raisedbest form raised air bedsaircraft support equipmentsbest support equipments for aircraftsbed air informercialsbest informercials bed airmattress sized air beds

bestair bed mattress antique doorknobsantique doorknob identification tipsdvd player troubleshootingtroubleshooting with the dvd playerflat panel television lcd vs plasmaflat panel lcd television versus plasma pic the bestThe causes of economic recessionwhat are the causes of economic recessionadjustable bed air foam The best bed air foam

hoof prints antique equestrian printsantique hoof prints equestrian printsBuy air bedadjustablebuy the best adjustable air bedsair beds canadian storesCanadian stores for air beds

migraine causemigraine treatments floridaflorida headache clinicdrying dessicantair drying dessicantdessicant air dryerpediatric asthmaasthma specialistasthma children specialistcarpet cleaning dallas txcarpet cleaners dallascarpet cleaning dallas

 

Post a Comment

<< Home