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?
19 Comments:
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());
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.
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.
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?
Brent: I tried that, but it only caused both FF and IE to invoke toString(), behaving the same as Safari :)
Why look for workarounds when you can get it fixed:
http://webkit.opendarwin.org/quality/reporting.html
(the bugreport for the safari team)
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...
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.
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.
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);
I found this fix today while researching this problem.
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?
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
Is it really that big of a deal? How much market share does Safari occupy anyway?
http://best-casino-online.t35.com Best Online Casino
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 ?
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
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
Excellent article and commentary! Online Penny Slots and Online Penny Slots Machines
Post a Comment
<< Home